mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-06-24 22:30:42 -04:00
fixed conflicts with upstream/master
This commit is contained in:
commit
4a76fddaa9
186 changed files with 6793 additions and 5999 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -17,3 +17,6 @@
|
||||||
[submodule "supportlibs/libsam3"]
|
[submodule "supportlibs/libsam3"]
|
||||||
path = supportlibs/libsam3
|
path = supportlibs/libsam3
|
||||||
url = https://github.com/i2p/libsam3.git
|
url = https://github.com/i2p/libsam3.git
|
||||||
|
[submodule "supportlibs/jni.hpp"]
|
||||||
|
path = supportlibs/jni.hpp
|
||||||
|
url = https://github.com/RetroShare/jni.hpp.git
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
## image name must match gitlab repository name, you can play just with the tag
|
## image name must match gitlab repository name, you can play just with the tag
|
||||||
## the part after :
|
## the part after :
|
||||||
# export CI_IMAGE_NAME="registry.gitlab.com/retroshare/retroshare:android_arm_base"
|
# export CI_IMAGE_NAME="registry.gitlab.com/retroshare/retroshare:android_arm_base"
|
||||||
# docker build --squash -t "${CI_REGISTRY_IMAGE}" \
|
# docker build --squash --tag "${CI_IMAGE_NAME}" \
|
||||||
# --build-arg QT_INSTALLER_JWT_TOKEN="your qt JWT token goes here" .
|
# --build-arg QT_INSTALLER_JWT_TOKEN="your qt JWT token goes here" .
|
||||||
#
|
#
|
||||||
# To build Android ARMv8 (64 bit) package pass also
|
# To build Android ARMv8 (64 bit) package pass also
|
||||||
|
@ -25,14 +25,16 @@
|
||||||
FROM ubuntu:20.04
|
FROM ubuntu:20.04
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
ENV APT_UNAT="--assume-yes --quiet"
|
||||||
|
|
||||||
RUN apt-get update && apt-get clean
|
RUN apt-get update $APT_UNAT && apt-get upgrade --show-upgraded $APT_UNAT && \
|
||||||
RUN apt-get install -y -qq \
|
apt-get clean $APT_UNAT
|
||||||
|
RUN apt-get install --no-install-recommends $APT_UNAT \
|
||||||
bash build-essential bzip2 cmake curl chrpath doxygen \
|
bash build-essential bzip2 cmake curl chrpath doxygen \
|
||||||
git p7zip python qt5-default qttools5-dev tclsh unzip wget zip
|
git p7zip python qt5-default qttools5-dev tclsh unzip wget zip
|
||||||
|
|
||||||
# Dependencies to create Android pkg
|
# Dependencies to create Android pkg
|
||||||
RUN apt-get install -y -qq \
|
RUN apt-get install --no-install-recommends $APT_UNAT \
|
||||||
openjdk-8-jre openjdk-8-jdk openjdk-8-jdk-headless gradle
|
openjdk-8-jre openjdk-8-jdk openjdk-8-jdk-headless gradle
|
||||||
|
|
||||||
ARG FRESHCLONE=0
|
ARG FRESHCLONE=0
|
||||||
|
@ -74,7 +76,7 @@ ARG QT_INSTALLER_JWT_TOKEN
|
||||||
RUN $PREPARE_TOOLCHAIN install_qt_android
|
RUN $PREPARE_TOOLCHAIN install_qt_android
|
||||||
# Avoid Qt account details leak into the image
|
# Avoid Qt account details leak into the image
|
||||||
RUN rm -f /root/.local/share/Qt/qtaccount.ini
|
RUN rm -f /root/.local/share/Qt/qtaccount.ini
|
||||||
# Shrink image by removing unneded Qt components
|
# Shrink image by removing unneeded Qt components
|
||||||
RUN rm -r \
|
RUN rm -r \
|
||||||
$NATIVE_LIBS_TOOLCHAIN_PATH/Qt/Docs/ \
|
$NATIVE_LIBS_TOOLCHAIN_PATH/Qt/Docs/ \
|
||||||
$NATIVE_LIBS_TOOLCHAIN_PATH/Qt/Examples/ \
|
$NATIVE_LIBS_TOOLCHAIN_PATH/Qt/Examples/ \
|
||||||
|
|
|
@ -112,6 +112,9 @@ define_default_value MVPTREE_SOURCE_VERSION origin/master
|
||||||
|
|
||||||
define_default_value REPORT_DIR "$(pwd)/$(basename ${NATIVE_LIBS_TOOLCHAIN_PATH})_build_report/"
|
define_default_value REPORT_DIR "$(pwd)/$(basename ${NATIVE_LIBS_TOOLCHAIN_PATH})_build_report/"
|
||||||
|
|
||||||
|
define_default_value RS_SRC_DIR "$(realpath $(dirname $BASH_SOURCE)/../../)"
|
||||||
|
|
||||||
|
|
||||||
cArch=""
|
cArch=""
|
||||||
eABI=""
|
eABI=""
|
||||||
cmakeABI=""
|
cmakeABI=""
|
||||||
|
@ -829,6 +832,15 @@ build_phash()
|
||||||
popd
|
popd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task_register fetch_jni_hpp
|
||||||
|
fetch_jni_hpp()
|
||||||
|
{
|
||||||
|
local rDir="supportlibs/jni.hpp/"
|
||||||
|
|
||||||
|
[ "$(ls "${RS_SRC_DIR}/${rDir}" | wc -l)" -gt "4" ] ||
|
||||||
|
git -C ${RS_SRC_DIR} submodule update --init ${rDir}
|
||||||
|
}
|
||||||
|
|
||||||
task_register build_mvptree
|
task_register build_mvptree
|
||||||
build_mvptree()
|
build_mvptree()
|
||||||
{
|
{
|
||||||
|
@ -862,6 +874,7 @@ build_default_toolchain()
|
||||||
task_run build_xapian || return $?
|
task_run build_xapian || return $?
|
||||||
task_run build_miniupnpc || return $?
|
task_run build_miniupnpc || return $?
|
||||||
task_run build_phash || return $?
|
task_run build_phash || return $?
|
||||||
|
task_run fetch_jni_hpp || return $?
|
||||||
task_run deduplicate_includes || return $?
|
task_run deduplicate_includes || return $?
|
||||||
task_run get_native_libs_toolchain_path || return $?
|
task_run get_native_libs_toolchain_path || return $?
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
ARG ANDROID_NDK_ARCH=arm
|
ARG ANDROID_NDK_ARCH=arm
|
||||||
FROM registry.gitlab.com/retroshare/retroshare:android_${ANDROID_NDK_ARCH}_base
|
FROM registry.gitlab.com/retroshare/retroshare:android_${ANDROID_NDK_ARCH}_base
|
||||||
|
|
||||||
RUN apt-get update -y && apt-get upgrade -y
|
ENV APT_UNAT="--assume-yes --quiet"
|
||||||
|
|
||||||
|
RUN apt-get update $APT_UNAT && apt-get upgrade $APT_UNAT --show-upgraded
|
||||||
|
|
||||||
ARG REPO_URL=https://gitlab.com/RetroShare/RetroShare.git
|
ARG REPO_URL=https://gitlab.com/RetroShare/RetroShare.git
|
||||||
ARG REPO_BRANCH=master
|
ARG REPO_BRANCH=master
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit b260e58346b1eec782bdf88a7e8f3c9d36fd3ecb
|
Subproject commit df16cb915465d058c75277678799ce4dadeae287
|
|
@ -1,447 +1,10 @@
|
||||||
// SPDX-FileCopyrightText: (C) 2004-2019 Retroshare Team <contact@retroshare.cc>
|
// SPDX-FileCopyrightText: (C) 2021 Retroshare Team <contact@retroshare.cc>
|
||||||
// SPDX-License-Identifier: CC0-1.0
|
// 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
|
This directory and all it's content is kept as is only for retro-compatibility
|
||||||
|
with the old, deprecated `qmake` build system.
|
||||||
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<std::string>+. 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<void (const RsGxsGroupSummary& result)>& 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<void (...)>+ 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
|
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
* RetroShare JSON API *
|
|
||||||
* *
|
|
||||||
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
|
||||||
* *
|
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
|
||||||
* it under the terms of the GNU 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 <https://www.gnu.org/licenses/>. *
|
|
||||||
* *
|
|
||||||
*******************************************************************************/
|
|
||||||
|
|
||||||
registerHandler( "$%apiPath%$",
|
|
||||||
[this](const std::shared_ptr<rb::Session> session)
|
|
||||||
{
|
|
||||||
const std::multimap<std::string, std::string> 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<rb::Session> session,
|
|
||||||
const rb::Bytes& body )
|
|
||||||
{
|
|
||||||
INITIALIZE_API_CALL_JSON_CONTEXT;
|
|
||||||
|
|
||||||
if( !checkRsServicePtrReady(
|
|
||||||
$%instanceName%$, "$%instanceName%$", cAns, session ) )
|
|
||||||
return;
|
|
||||||
|
|
||||||
$%paramsDeclaration%$
|
|
||||||
|
|
||||||
$%inputParamsDeserialization%$
|
|
||||||
|
|
||||||
const std::weak_ptr<rb::Service> weakService(mService);
|
|
||||||
const std::weak_ptr<rb::Session> 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%$ );
|
|
1
jsonapi-generator/src/async-method-wrapper-template.cpp.tmpl
Symbolic link
1
jsonapi-generator/src/async-method-wrapper-template.cpp.tmpl
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../libretroshare/src/jsonapi/async-method-wrapper-template.cpp.tmpl
|
|
@ -1,230 +0,0 @@
|
||||||
DOXYFILE_ENCODING = UTF-8
|
|
||||||
PROJECT_NAME = "libretroshare"
|
|
||||||
|
|
||||||
ALIASES += jsonapi{1}="\xmlonly<jsonapi minversion=\"\1\"/>\endxmlonly"
|
|
||||||
ALIASES += jsonapi{2}="\xmlonly<jsonapi minversion=\"\1\" access=\"\2\"/>\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
|
|
||||||
|
|
1
jsonapi-generator/src/jsonapi-generator-doxygen.conf
Symbolic link
1
jsonapi-generator/src/jsonapi-generator-doxygen.conf
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../libretroshare/src/jsonapi/jsonapi-generator-doxygen.conf
|
|
@ -1,50 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
* RetroShare JSON API *
|
|
||||||
* *
|
|
||||||
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
|
||||||
* *
|
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
|
||||||
* it under the terms of the GNU Affero General Public License as *
|
|
||||||
* published by the Free Software Foundation, either version 3 of the *
|
|
||||||
* License, or (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
* This program is distributed in the hope that it will be useful, *
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
||||||
* GNU Affero General Public License for more details. *
|
|
||||||
* *
|
|
||||||
* You should have received a copy of the GNU Affero General Public License *
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
|
||||||
* *
|
|
||||||
*******************************************************************************/
|
|
||||||
|
|
||||||
registerHandler( "$%apiPath%$",
|
|
||||||
[](const std::shared_ptr<rb::Session> session)
|
|
||||||
{
|
|
||||||
size_t reqSize = session->get_request()->get_header("Content-Length", 0);
|
|
||||||
session->fetch( reqSize, [](
|
|
||||||
const std::shared_ptr<rb::Session> 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%$ );
|
|
||||||
|
|
1
jsonapi-generator/src/method-wrapper-template.cpp.tmpl
Symbolic link
1
jsonapi-generator/src/method-wrapper-template.cpp.tmpl
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../libretroshare/src/jsonapi/method-wrapper-template.cpp.tmpl
|
19
libbitdht/CMakeLists.txt
Normal file
19
libbitdht/CMakeLists.txt
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# RetroShare decentralized communication platform
|
||||||
|
#
|
||||||
|
# Copyright (C) 2021 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||||
|
# Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
cmake_minimum_required (VERSION 2.8.12)
|
||||||
|
project(bitdht)
|
||||||
|
|
||||||
|
file(
|
||||||
|
GLOB BITDHT_SOURCES
|
||||||
|
src/bitdht/*.c src/bitdht/*.cc src/udp/*.cc src/util/*.cc )
|
||||||
|
|
||||||
|
add_library(${PROJECT_NAME} ${BITDHT_SOURCES})
|
||||||
|
|
||||||
|
target_include_directories(
|
||||||
|
${PROJECT_NAME}
|
||||||
|
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src )
|
411
libretroshare/CMakeLists.txt
Normal file
411
libretroshare/CMakeLists.txt
Normal file
|
@ -0,0 +1,411 @@
|
||||||
|
# RetroShare decentralized communication platform
|
||||||
|
#
|
||||||
|
# Copyright (C) 2021 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||||
|
# Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
cmake_minimum_required (VERSION 3.18.0)
|
||||||
|
project(retroshare)
|
||||||
|
|
||||||
|
include(CMakeDependentOption)
|
||||||
|
|
||||||
|
set(FETCHCONTENT_QUIET OFF)
|
||||||
|
include(FetchContent)
|
||||||
|
|
||||||
|
# sqlcipher
|
||||||
|
option(
|
||||||
|
RS_SQLCIPHER
|
||||||
|
"SQLCipher encryption for GXS database"
|
||||||
|
ON )
|
||||||
|
|
||||||
|
# rs_gxs_send_all
|
||||||
|
option(
|
||||||
|
RS_GXS_SEND_ALL
|
||||||
|
"GXS distribute all available messages on request, indipendently from \
|
||||||
|
local sync timer"
|
||||||
|
ON )
|
||||||
|
|
||||||
|
# bitdht
|
||||||
|
option(
|
||||||
|
RS_BITDHT
|
||||||
|
"Use bitdht (BitTorrent DHT own implementation) to look for online peers"
|
||||||
|
ON )
|
||||||
|
|
||||||
|
# use_dht_stunner
|
||||||
|
cmake_dependent_option(
|
||||||
|
RS_BITDHT_STUNNER
|
||||||
|
"Use bitdht (BitTorrent DHT own implementation) for NAT type discovery and \
|
||||||
|
attempt the STUN (Session Traversal Utilities for NAT)"
|
||||||
|
ON
|
||||||
|
"RS_BITDHT"
|
||||||
|
OFF )
|
||||||
|
|
||||||
|
# use_dht_stunner_ext_ip
|
||||||
|
cmake_dependent_option(
|
||||||
|
RS_BITDHT_STUNNER_EXT_IP
|
||||||
|
"Use bitdht (BitTorrent DHT own implementation) stunner to figure out our \
|
||||||
|
external IP. As this purely relying on random DHT peers that answer our \
|
||||||
|
request, it can easily be abused. Therefore, it is turned off by default."
|
||||||
|
OFF
|
||||||
|
"RS_BITDHT_STUNNER"
|
||||||
|
OFF )
|
||||||
|
|
||||||
|
# rs_jsonapi
|
||||||
|
option(
|
||||||
|
RS_JSON_API
|
||||||
|
"Use restbed to expose libretroshare as JSON API via HTTP"
|
||||||
|
OFF )
|
||||||
|
|
||||||
|
# rs_deep_forums_index
|
||||||
|
option(
|
||||||
|
RS_FORUM_DEEP_INDEX
|
||||||
|
"Xapian based full text index and search of GXS forums"
|
||||||
|
OFF )
|
||||||
|
|
||||||
|
# rs_broadcast_discovery
|
||||||
|
option(
|
||||||
|
RS_BRODCAST_DISCOVERY
|
||||||
|
"Local area network peer discovery via udp-discovery-cpp"
|
||||||
|
ON )
|
||||||
|
|
||||||
|
# rs_dh_init_check
|
||||||
|
option(
|
||||||
|
RS_DH_PRIME_INIT_CHECK
|
||||||
|
"Check Diffie Hellman prime at each startup. This is not necessary and on \
|
||||||
|
all Android mobile phones tested this take at least one minute at startup \
|
||||||
|
which is untolerable for most phone users."
|
||||||
|
ON )
|
||||||
|
|
||||||
|
option(
|
||||||
|
RS_MINIUPNPC
|
||||||
|
"Forward ports in NAT router via miniupnpc"
|
||||||
|
ON )
|
||||||
|
|
||||||
|
cmake_dependent_option(
|
||||||
|
RS_LIBUPNP
|
||||||
|
"Forward ports in NAT router via libupnp (unstable)"
|
||||||
|
OFF
|
||||||
|
"NOT RS_MINIUPNPC"
|
||||||
|
OFF )
|
||||||
|
|
||||||
|
option(
|
||||||
|
RS_LIBRETROSHARE_STATIC
|
||||||
|
"Build RetroShare static library"
|
||||||
|
ON )
|
||||||
|
|
||||||
|
cmake_dependent_option(
|
||||||
|
RS_LIBRETROSHARE_SHARED
|
||||||
|
"Build RetroShare shared library"
|
||||||
|
OFF
|
||||||
|
"NOT RS_LIBRETROSHARE_STATIC"
|
||||||
|
OFF )
|
||||||
|
|
||||||
|
# rs_deprecatedwarning
|
||||||
|
option(
|
||||||
|
RS_WARN_DEPRECATED
|
||||||
|
"Print warning about RetroShare deprecated components usage during build"
|
||||||
|
ON )
|
||||||
|
|
||||||
|
# rs_cppwarning
|
||||||
|
option(
|
||||||
|
RS_WARN_LESS
|
||||||
|
"Silence a few at the moment very common warnings about RetroShare \
|
||||||
|
components during build"
|
||||||
|
OFF )
|
||||||
|
|
||||||
|
# rs_v07_changes
|
||||||
|
option(
|
||||||
|
RS_V07_BREAKING_CHANGES
|
||||||
|
"Enable retro-compatibility breaking changes planned for RetroShare 0.7.0"
|
||||||
|
OFF )
|
||||||
|
|
||||||
|
set(
|
||||||
|
RS_DATA_DIR
|
||||||
|
"${CMAKE_INSTALL_PREFIX}/share/retroshare"
|
||||||
|
CACHE STRING
|
||||||
|
"Path where to install RetroShare system wide data" )
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
find_package(Git REQUIRED)
|
||||||
|
|
||||||
|
#function(check_submodule sPath)
|
||||||
|
# if(NOT EXISTS "${sPath}/.git" )
|
||||||
|
# message("Initializing submodule ${sPath}")
|
||||||
|
# execute_process(
|
||||||
|
# COMMAND "${GIT_EXECUTABLE}" submodule update --init
|
||||||
|
# WORKING_DIRECTORY "${sPath}"
|
||||||
|
# COMMAND_ECHO STDERR
|
||||||
|
# COMMAND_ERROR_IS_FATAL ANY)
|
||||||
|
# endif()
|
||||||
|
#endfunction()
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
include(src/CMakeLists.txt)
|
||||||
|
list(TRANSFORM RS_SOURCES PREPEND src/)
|
||||||
|
list(TRANSFORM RS_PUBLIC_HEADERS PREPEND src/)
|
||||||
|
|
||||||
|
if(RS_LIBRETROSHARE_STATIC)
|
||||||
|
add_library(${PROJECT_NAME} STATIC ${RS_SOURCES})
|
||||||
|
endif(RS_LIBRETROSHARE_STATIC)
|
||||||
|
|
||||||
|
if(RS_LIBRETROSHARE_SHARED)
|
||||||
|
add_library(${PROJECT_NAME} SHARED ${RS_SOURCES})
|
||||||
|
|
||||||
|
## Ensure statically linked libraries such as openpgpsdk are compiled with
|
||||||
|
## PIC Which is needed for shared library
|
||||||
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
|
endif(RS_LIBRETROSHARE_SHARED)
|
||||||
|
|
||||||
|
target_include_directories(
|
||||||
|
${PROJECT_NAME}
|
||||||
|
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src )
|
||||||
|
|
||||||
|
|
||||||
|
find_package(OpenSSL REQUIRED)
|
||||||
|
target_include_directories(${PROJECT_NAME} PRIVATE ${OPENSSL_INCLUDE_DIR})
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE OpenSSL::SSL OpenSSL::Crypto)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
set(OPENPGPSDK_DEVEL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../openpgpsdk/")
|
||||||
|
if(EXISTS "${OPENPGPSDK_DEVEL_DIR}/.git" )
|
||||||
|
message(
|
||||||
|
CHECK_PASS
|
||||||
|
"openpgpsdk submodule found at ${OPENPGPSDK_DEVEL_DIR} using it" )
|
||||||
|
add_subdirectory(${OPENPGPSDK_DEVEL_DIR} ${CMAKE_BINARY_DIR}/openpgpsdk)
|
||||||
|
else()
|
||||||
|
FetchContent_Declare(
|
||||||
|
openpgpsdk
|
||||||
|
GIT_REPOSITORY "https://gitlab.com/RetroShare/openpgpsdk.git"
|
||||||
|
GIT_TAG "origin/master"
|
||||||
|
GIT_SHALLOW TRUE
|
||||||
|
GIT_PROGRESS TRUE
|
||||||
|
TIMEOUT 10
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(openpgpsdk)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE openpgpsdk)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
if(RS_BITDHT)
|
||||||
|
set(BITDHT_DEVEL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../libbitdht/")
|
||||||
|
if(EXISTS "${BITDHT_DEVEL_DIR}/.git" )
|
||||||
|
message(
|
||||||
|
CHECK_PASS
|
||||||
|
"BitDHT submodule found at ${BITDHT_DEVEL_DIR} using it" )
|
||||||
|
add_subdirectory(${BITDHT_DEVEL_DIR} ${CMAKE_BINARY_DIR}/bitdht)
|
||||||
|
else()
|
||||||
|
FetchContent_Declare(
|
||||||
|
bitdht
|
||||||
|
GIT_REPOSITORY "https://gitlab.com/RetroShare/bitdht.git"
|
||||||
|
GIT_TAG "origin/master"
|
||||||
|
GIT_SHALLOW TRUE
|
||||||
|
GIT_PROGRESS TRUE
|
||||||
|
TIMEOUT 10
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(bitdht)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_compile_definitions(RS_USE_BITDHT)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE bitdht)
|
||||||
|
|
||||||
|
if(RS_BITDHT_STUNNER)
|
||||||
|
add_compile_definitions(RS_USE_DHT_STUNNER)
|
||||||
|
|
||||||
|
if(RS_BITDHT_STUNNER_EXT_IP)
|
||||||
|
# TODO: Refactor this define to use proper naming
|
||||||
|
add_compile_definitions(ALLOW_DHT_STUNNER)
|
||||||
|
endif(RS_BITDHT_STUNNER_EXT_IP)
|
||||||
|
endif(RS_BITDHT_STUNNER)
|
||||||
|
endif(RS_BITDHT)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
if(RS_JSON_API)
|
||||||
|
find_package(Doxygen REQUIRED)
|
||||||
|
find_package(Python3 REQUIRED)
|
||||||
|
|
||||||
|
## TODO: execute at build time instead that at cofiguration time see
|
||||||
|
## add_custom_command or add_custom_target
|
||||||
|
|
||||||
|
set(
|
||||||
|
JSON_API_GENERATOR_WORK_DIR
|
||||||
|
"${CMAKE_BINARY_DIR}/jsonapi-generator.workdir/" )
|
||||||
|
|
||||||
|
set(
|
||||||
|
JSON_API_GENERATOR_DOXYFILE
|
||||||
|
"${JSON_API_GENERATOR_WORK_DIR}/jsonapi-generator-doxygen.conf" )
|
||||||
|
|
||||||
|
set(
|
||||||
|
JSONAPI_GENERATOR_OUTPUT_DIR
|
||||||
|
"${JSON_API_GENERATOR_WORK_DIR}/src/" )
|
||||||
|
|
||||||
|
set(
|
||||||
|
JSONAPI_GENERATOR_SOURCE_DIR
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/jsonapi/" )
|
||||||
|
|
||||||
|
set(
|
||||||
|
JSONAPI_GENERATOR_EXECUTABLE
|
||||||
|
"${JSONAPI_GENERATOR_SOURCE_DIR}/jsonapi-generator.py" )
|
||||||
|
|
||||||
|
file(
|
||||||
|
COPY "src/jsonapi/jsonapi-generator-doxygen.conf"
|
||||||
|
DESTINATION "${JSON_API_GENERATOR_WORK_DIR}" )
|
||||||
|
|
||||||
|
file(
|
||||||
|
APPEND
|
||||||
|
"${JSON_API_GENERATOR_DOXYFILE}"
|
||||||
|
"OUTPUT_DIRECTORY=${JSONAPI_GENERATOR_OUTPUT_DIR}\n"
|
||||||
|
"INPUT=${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT
|
||||||
|
"${JSONAPI_GENERATOR_OUTPUT_DIR}/jsonapi-includes.inl"
|
||||||
|
"${JSONAPI_GENERATOR_OUTPUT_DIR}/jsonapi-wrappers.inl"
|
||||||
|
COMMAND ${DOXYGEN_EXECUTABLE} ${JSON_API_GENERATOR_DOXYFILE}
|
||||||
|
COMMAND
|
||||||
|
${Python3_EXECUTABLE} ${JSONAPI_GENERATOR_EXECUTABLE}
|
||||||
|
${JSONAPI_GENERATOR_SOURCE_DIR} ${JSONAPI_GENERATOR_OUTPUT_DIR}
|
||||||
|
MAIN_DEPENDENCY "${JSONAPI_GENERATOR_EXECUTABLE}"
|
||||||
|
DEPENDS ${JSON_API_GENERATOR_DOXYFILE} ${RS_PUBLIC_HEADERS} )
|
||||||
|
|
||||||
|
target_sources(
|
||||||
|
${PROJECT_NAME} PRIVATE
|
||||||
|
"${JSONAPI_GENERATOR_OUTPUT_DIR}/jsonapi-includes.inl"
|
||||||
|
"${JSONAPI_GENERATOR_OUTPUT_DIR}/jsonapi-wrappers.inl" )
|
||||||
|
|
||||||
|
include_directories(${JSONAPI_GENERATOR_OUTPUT_DIR})
|
||||||
|
|
||||||
|
set(BUILD_TESTS OFF CACHE BOOL "Do not build restbed tests")
|
||||||
|
set(BUILD_SSL OFF CACHE BOOL "Do not build restbed SSL support")
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
restbed
|
||||||
|
GIT_REPOSITORY "https://github.com/Corvusoft/restbed.git"
|
||||||
|
GIT_TAG "4.8"
|
||||||
|
GIT_SUBMODULES dependency/asio dependency/catch
|
||||||
|
GIT_SHALLOW TRUE
|
||||||
|
GIT_PROGRESS TRUE
|
||||||
|
TIMEOUT 10
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(restbed)
|
||||||
|
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE restbed)
|
||||||
|
|
||||||
|
## TODO: work around target_include_directories should be added upstream
|
||||||
|
include_directories(${restbed_SOURCE_DIR}/source/)
|
||||||
|
|
||||||
|
add_compile_definitions(RS_JSONAPI)
|
||||||
|
endif(RS_JSON_API)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
if(RS_FORUM_DEEP_INDEX)
|
||||||
|
find_package(Xapian REQUIRED)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE ${XAPIAN_LIBRARIES})
|
||||||
|
|
||||||
|
add_compile_definitions(RS_DEEP_FORUMS_INDEX)
|
||||||
|
endif(RS_FORUM_DEEP_INDEX)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
## TODO: Check if https://github.com/rbock/sqlpp11 or
|
||||||
|
## https://github.com/rbock/sqlpp17 may improve GXS code
|
||||||
|
if(RS_SQLCIPHER)
|
||||||
|
find_library(RS_SQL_LIB "sqlcipher" REQUIRED)
|
||||||
|
find_path(
|
||||||
|
RS_SQL_LIB_INCLUDE "sqlcipher/sqlite3.h"
|
||||||
|
PATH_SUFFIXES "include" "includes"
|
||||||
|
REQUIRED )
|
||||||
|
target_include_directories(
|
||||||
|
${PROJECT_NAME}
|
||||||
|
PRIVATE "${RS_SQL_LIB_INCLUDE}/sqlcipher" )
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE ${RS_SQL_LIB})
|
||||||
|
else()
|
||||||
|
add_compile_definitions(NO_SQLCIPHER)
|
||||||
|
find_package(SQLite3 REQUIRED)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE SQLite::SQLite3)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_compile_definitions(
|
||||||
|
SQLITE_HAS_CODEC
|
||||||
|
RS_ENABLE_GXS
|
||||||
|
GXS_ENABLE_SYNC_MSGS
|
||||||
|
RS_USE_GXS_DISTANT_SYNC
|
||||||
|
RS_GXS_TRANS
|
||||||
|
V07_NON_BACKWARD_COMPATIBLE_CHANGE_001
|
||||||
|
V07_NON_BACKWARD_COMPATIBLE_CHANGE_002
|
||||||
|
V07_NON_BACKWARD_COMPATIBLE_CHANGE_003 )
|
||||||
|
|
||||||
|
if(RS_V07_BREAKING_CHANGES)
|
||||||
|
add_compile_definitions(
|
||||||
|
V07_NON_BACKWARD_COMPATIBLE_CHANGE_004
|
||||||
|
V07_NON_BACKWARD_COMPATIBLE_CHANGE_UNNAMED )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(RS_DH_PRIME_INIT_CHECK)
|
||||||
|
add_compile_definitions(RS_DISABLE_DIFFIE_HELLMAN_INIT_CHECK)
|
||||||
|
endif(RS_DH_PRIME_INIT_CHECK)
|
||||||
|
|
||||||
|
if(RS_MINIUPNPC)
|
||||||
|
add_compile_definitions(RS_USE_LIBMINIUPNPC)
|
||||||
|
endif(RS_MINIUPNPC)
|
||||||
|
|
||||||
|
if(RS_LIBUPNP)
|
||||||
|
message(FATAL_ERROR "UPnP support via libupnp is currently not supported")
|
||||||
|
#add_compile_definitions(RS_USE_LIBUPNP)
|
||||||
|
endif(RS_LIBUPNP)
|
||||||
|
|
||||||
|
if(RS_GXS_SEND_ALL)
|
||||||
|
add_compile_definitions(RS_GXS_SEND_ALL)
|
||||||
|
endif(RS_GXS_SEND_ALL)
|
||||||
|
|
||||||
|
if(RS_BRODCAST_DISCOVERY)
|
||||||
|
## TODO: upstream option to disable tests building
|
||||||
|
set(BUILD_EXAMPLE OFF CACHE BOOL "Do not build udp-discovery-cpp examples")
|
||||||
|
set(BUILD_TOOL OFF CACHE BOOL "Do not build udp-discovery-tool application")
|
||||||
|
FetchContent_Declare(
|
||||||
|
udp-discovery-cpp
|
||||||
|
GIT_REPOSITORY "https://github.com/truvorskameikin/udp-discovery-cpp.git"
|
||||||
|
GIT_TAG "origin/master"
|
||||||
|
GIT_SHALLOW TRUE
|
||||||
|
GIT_PROGRESS TRUE
|
||||||
|
TIMEOUT 10
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(udp-discovery-cpp)
|
||||||
|
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE udp-discovery-cpp)
|
||||||
|
|
||||||
|
## TODO: Temporary work around target_include_directories should be added
|
||||||
|
## upstream
|
||||||
|
include_directories(${udp-discovery-cpp_SOURCE_DIR})
|
||||||
|
endif(RS_BRODCAST_DISCOVERY)
|
||||||
|
|
||||||
|
if(NOT RS_WARN_DEPRECATED)
|
||||||
|
add_compile_definitions(RS_NO_WARN_DEPRECATED)
|
||||||
|
target_compile_options(
|
||||||
|
${PROJECT_NAME} PRIVATE
|
||||||
|
-Wno-deprecated -Wno-deprecated-declarations )
|
||||||
|
endif(NOT RS_WARN_DEPRECATED)
|
||||||
|
|
||||||
|
if(RS_WARN_LESS)
|
||||||
|
add_compile_definitions(RS_NO_WARN_CPP)
|
||||||
|
|
||||||
|
target_compile_options(
|
||||||
|
${PROJECT_NAME} PRIVATE
|
||||||
|
-Wno-cpp -Wno-inconsistent-missing-override )
|
||||||
|
endif(RS_WARN_LESS)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
add_compile_definitions(RS_DATA_DIR="${RS_DATA_DIR}")
|
||||||
|
endif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
|
||||||
|
## Useful to debug CMake
|
||||||
|
#set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
408
libretroshare/src/CMakeLists.txt
Normal file
408
libretroshare/src/CMakeLists.txt
Normal file
|
@ -0,0 +1,408 @@
|
||||||
|
# RetroShare decentralized communication platform
|
||||||
|
#
|
||||||
|
# Copyright (C) 2021 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||||
|
# Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
list(
|
||||||
|
APPEND RS_PUBLIC_HEADERS
|
||||||
|
retroshare/rsexpr.h
|
||||||
|
retroshare/rsgxsdistsync.h
|
||||||
|
retroshare/rsiface.h
|
||||||
|
retroshare/rsrtt.h
|
||||||
|
retroshare/rsbanlist.h
|
||||||
|
retroshare/rsconfig.h
|
||||||
|
retroshare/rsdisc.h
|
||||||
|
retroshare/rsflags.h
|
||||||
|
retroshare/rsgrouter.h
|
||||||
|
retroshare/rsgxsflags.h
|
||||||
|
retroshare/rsgxsservice.h
|
||||||
|
retroshare/rsgxstrans.h
|
||||||
|
retroshare/rsgxstunnel.h
|
||||||
|
retroshare/rsids.h
|
||||||
|
retroshare/rsnotify.h
|
||||||
|
retroshare/rsphoto.h
|
||||||
|
retroshare/rsplugin.h
|
||||||
|
retroshare/rsreputations.h
|
||||||
|
retroshare/rsservicecontrol.h
|
||||||
|
retroshare/rstokenservice.h
|
||||||
|
retroshare/rsturtle.h
|
||||||
|
retroshare/rsgossipdiscovery.h
|
||||||
|
retroshare/rsgxscommon.h
|
||||||
|
retroshare/rsposted.h
|
||||||
|
retroshare/rsstatus.h
|
||||||
|
retroshare/rsversion.h
|
||||||
|
retroshare/rsgxsifacehelper.h
|
||||||
|
retroshare/rshistory.h
|
||||||
|
retroshare/rsidentity.h
|
||||||
|
retroshare/rsmsgs.h
|
||||||
|
retroshare/rsgxschannels.h
|
||||||
|
retroshare/rsgxscircles.h
|
||||||
|
retroshare/rsgxsiface.h
|
||||||
|
retroshare/rsgxsifacetypes.h
|
||||||
|
retroshare/rstypes.h
|
||||||
|
retroshare/rsgxsforums.h
|
||||||
|
retroshare/rsevents.h
|
||||||
|
retroshare/rsfiles.h
|
||||||
|
retroshare/rsinit.h
|
||||||
|
retroshare/rspeers.h )
|
||||||
|
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
chat/distantchat.cc
|
||||||
|
chat/p3chatservice.cc
|
||||||
|
chat/rschatitems.cc
|
||||||
|
chat/distributedchat.cc
|
||||||
|
crypto/chacha20.cpp
|
||||||
|
crypto/hashstream.cc
|
||||||
|
crypto/rsaes.cc
|
||||||
|
crypto/rscrypto.cpp )
|
||||||
|
|
||||||
|
if(RS_BITDHT)
|
||||||
|
list(
|
||||||
|
APPEND RS_PUBLIC_HEADERS
|
||||||
|
retroshare/rsdht.h )
|
||||||
|
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
dht/connectstatebox.cc
|
||||||
|
dht/p3bitdht.cc
|
||||||
|
dht/p3bitdht_interface.cc
|
||||||
|
dht/p3bitdht_peernet.cc
|
||||||
|
dht/p3bitdht_peers.cc
|
||||||
|
dht/p3bitdht_relay.cc )
|
||||||
|
endif(RS_BITDHT)
|
||||||
|
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
file_sharing/filelist_io.cc
|
||||||
|
file_sharing/rsfilelistitems.cc
|
||||||
|
file_sharing/file_tree.cc
|
||||||
|
file_sharing/directory_updater.cc
|
||||||
|
file_sharing/p3filelists.cc
|
||||||
|
file_sharing/hash_cache.cc
|
||||||
|
file_sharing/dir_hierarchy.cc
|
||||||
|
file_sharing/directory_storage.cc
|
||||||
|
ft/ftchunkmap.cc
|
||||||
|
ft/ftfilecreator.cc
|
||||||
|
ft/ftfileprovider.cc
|
||||||
|
ft/ftfilesearch.cc
|
||||||
|
ft/ftturtlefiletransferitem.cc
|
||||||
|
ft/fttransfermodule.cc
|
||||||
|
ft/ftcontroller.cc
|
||||||
|
ft/ftdatamultiplex.cc
|
||||||
|
ft/ftextralist.cc
|
||||||
|
ft/ftserver.cc )
|
||||||
|
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
grouter/groutermatrix.cc
|
||||||
|
grouter/grouteritems.cc
|
||||||
|
grouter/p3grouter.cc )
|
||||||
|
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
gxs/rsgxsdata.cc
|
||||||
|
gxs/rsgxsrequesttypes.cc
|
||||||
|
gxs/gxssecurity.cc
|
||||||
|
gxs/gxstokenqueue.cc
|
||||||
|
gxs/rsdataservice.cc
|
||||||
|
gxs/rsgxsdataaccess.cc
|
||||||
|
gxs/rsgxsnetutils.cc
|
||||||
|
gxs/rsgxsnettunnel.cc
|
||||||
|
gxs/rsgxsutil.cc
|
||||||
|
gxs/rsnxsobserver.cpp
|
||||||
|
gxs/rsgenexchange.cc
|
||||||
|
gxs/rsgxsnetservice.cc )
|
||||||
|
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
gxstrans/p3gxstransitems.cc
|
||||||
|
gxstrans/p3gxstrans.cc )
|
||||||
|
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
gxstunnel/rsgxstunnelitems.cc
|
||||||
|
gxstunnel/p3gxstunnel.cc )
|
||||||
|
|
||||||
|
if(RS_JSON_API)
|
||||||
|
list(
|
||||||
|
APPEND RS_PUBLIC_HEADERS
|
||||||
|
retroshare/rsjsonapi.h )
|
||||||
|
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
jsonapi/jsonapi.cpp )
|
||||||
|
endif(RS_JSON_API)
|
||||||
|
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
pgp/pgpkeyutil.cc
|
||||||
|
pgp/pgpauxutils.cc
|
||||||
|
pgp/pgphandler.cc
|
||||||
|
pgp/rscertificate.cc )
|
||||||
|
|
||||||
|
#./plugins/dlfcn_win32.cc
|
||||||
|
#./plugins/dlfcn_win32.h
|
||||||
|
#./plugins/pluginmanager.h
|
||||||
|
#./plugins/rscacheservice.h
|
||||||
|
#./plugins/rspqiservice.h
|
||||||
|
#./plugins/pluginmanager.cc
|
||||||
|
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
pqi/pqibin.cc
|
||||||
|
pqi/pqiipset.cc
|
||||||
|
pqi/pqiloopback.cc
|
||||||
|
pqi/pqimonitor.cc
|
||||||
|
pqi/pqipersongrp.cc
|
||||||
|
pqi/pqiqos.cc
|
||||||
|
pqi/pqiqosstreamer.cc
|
||||||
|
pqi/pqisslproxy.cc
|
||||||
|
pqi/pqistore.cc
|
||||||
|
pqi/authgpg.cc
|
||||||
|
pqi/p3cfgmgr.cc
|
||||||
|
pqi/p3notify.cc
|
||||||
|
pqi/p3servicecontrol.cc
|
||||||
|
pqi/pqinetstatebox.cc
|
||||||
|
pqi/pqiperson.cc
|
||||||
|
pqi/pqiservice.cc
|
||||||
|
pqi/pqissllistener.cc
|
||||||
|
pqi/pqissludp.cc
|
||||||
|
pqi/pqithreadstreamer.cc
|
||||||
|
pqi/sslfns.cc
|
||||||
|
pqi/authssl.cc
|
||||||
|
pqi/p3historymgr.cc
|
||||||
|
pqi/p3linkmgr.cc
|
||||||
|
pqi/pqihandler.cc
|
||||||
|
pqi/pqistreamer.cc
|
||||||
|
pqi/p3netmgr.cc
|
||||||
|
pqi/p3peermgr.cc
|
||||||
|
pqi/pqinetwork.cc
|
||||||
|
pqi/pqissl.cc
|
||||||
|
pqi/pqisslpersongrp.cc )
|
||||||
|
|
||||||
|
#./pqi/pqissli2psam3.cpp
|
||||||
|
#./pqi/pqissli2psam3.h
|
||||||
|
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
rsitems/rsbanlistitems.cc
|
||||||
|
rsitems/rsbwctrlitems.cc
|
||||||
|
rsitems/rsconfigitems.cc
|
||||||
|
rsitems/rsfiletransferitems.cc
|
||||||
|
rsitems/rsgxscommentitems.cc
|
||||||
|
rsitems/rsgxsforumitems.cc
|
||||||
|
rsitems/rsgxsiditems.cc
|
||||||
|
rsitems/rsgxsrecognitems.cc
|
||||||
|
rsitems/rsgxsreputationitems.cc
|
||||||
|
rsitems/rsgxsupdateitems.cc
|
||||||
|
rsitems/rshistoryitems.cc
|
||||||
|
rsitems/rsrttitems.cc
|
||||||
|
rsitems/rsserviceinfoitems.cc )
|
||||||
|
|
||||||
|
#retroshare/rswiki.h
|
||||||
|
#./rsitems/rswikiitems.cc
|
||||||
|
#./rsitems/rswikiitems.h
|
||||||
|
#./rsitems/rswireitems.h
|
||||||
|
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
rsitems/rsgxschannelitems.cc
|
||||||
|
rsitems/rsgxscircleitems.cc
|
||||||
|
rsitems/rsgxsitems.cc
|
||||||
|
rsitems/rsmsgitems.cc )
|
||||||
|
|
||||||
|
#./rsitems/rsphotoitems.cc
|
||||||
|
#./rsitems/rsphotoitems.h
|
||||||
|
#./rsitems/rsposteditems.cc
|
||||||
|
#./rsitems/rsposteditems.h
|
||||||
|
#./rsitems/rswireitems.cc
|
||||||
|
#retroshare/rswire.h
|
||||||
|
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
rsitems/rsnxsitems.cc )
|
||||||
|
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
rsserver/p3status.cc
|
||||||
|
rsserver/p3face-config.cc
|
||||||
|
rsserver/p3face-info.cc
|
||||||
|
rsserver/p3history.cc
|
||||||
|
rsserver/p3serverconfig.cc
|
||||||
|
rsserver/rsloginhandler.cc
|
||||||
|
rsserver/p3face-server.cc
|
||||||
|
rsserver/p3msgs.cc
|
||||||
|
rsserver/p3peers.cc
|
||||||
|
rsserver/rsaccounts.cc
|
||||||
|
rsserver/rsinit.cc )
|
||||||
|
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
serialiser/rsbaseserial.cc
|
||||||
|
serialiser/rsserializable.cc
|
||||||
|
serialiser/rstlvaddrs.cc
|
||||||
|
serialiser/rstlvbanlist.cc
|
||||||
|
serialiser/rstlvbase.cc
|
||||||
|
serialiser/rstlvbinary.cc
|
||||||
|
serialiser/rstlvfileitem.cc
|
||||||
|
serialiser/rstlvgenericmap.inl
|
||||||
|
serialiser/rstlvgenericparam.cc
|
||||||
|
serialiser/rstlvidset.cc
|
||||||
|
serialiser/rstlvimage.cc
|
||||||
|
serialiser/rstlvitem.cc
|
||||||
|
serialiser/rstlvkeys.cc
|
||||||
|
serialiser/rstlvkeyvalue.cc
|
||||||
|
serialiser/rstlvstring.cc
|
||||||
|
serialiser/rsserializer.cc
|
||||||
|
serialiser/rstypeserializer.cc
|
||||||
|
serialiser/rsserial.cc )
|
||||||
|
|
||||||
|
# ./services/autoproxy
|
||||||
|
#./services/autoproxy/p3i2psam3.cpp
|
||||||
|
#./services/autoproxy/p3i2psam3.h
|
||||||
|
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
services/autoproxy/rsautoproxymonitor.cc
|
||||||
|
services/p3bwctrl.cc
|
||||||
|
services/p3heartbeat.cc
|
||||||
|
services/p3service.cc
|
||||||
|
services/p3serviceinfo.cc
|
||||||
|
services/p3statusservice.cc
|
||||||
|
services/p3banlist.cc
|
||||||
|
services/p3rtt.cc
|
||||||
|
services/rseventsservice.cc
|
||||||
|
services/p3gxscircles.cc
|
||||||
|
services/p3gxscommon.cc
|
||||||
|
services/p3gxsreputation.cc
|
||||||
|
services/p3msgservice.cc
|
||||||
|
services/p3idservice.cc
|
||||||
|
services/p3gxschannels.cc
|
||||||
|
services/p3gxsforums.cc )
|
||||||
|
|
||||||
|
#./services/p3wiki.cc
|
||||||
|
#./services/p3wiki.h
|
||||||
|
#./services/p3wire.cc
|
||||||
|
#./services/p3wire.h
|
||||||
|
|
||||||
|
#./services/p3photoservice.cc
|
||||||
|
#./services/p3photoservice.h
|
||||||
|
#./services/p3postbase.cc
|
||||||
|
#./services/p3postbase.h
|
||||||
|
#./services/p3posted.cc
|
||||||
|
#./services/p3posted.h
|
||||||
|
|
||||||
|
if(RS_BRODCAST_DISCOVERY)
|
||||||
|
list(
|
||||||
|
APPEND RS_PUBLIC_HEADERS
|
||||||
|
retroshare/rsbroadcastdiscovery.h )
|
||||||
|
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
services/broadcastdiscoveryservice.cc )
|
||||||
|
endif(RS_BRODCAST_DISCOVERY)
|
||||||
|
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
tcponudp/tcppacket.cc
|
||||||
|
tcponudp/tcpstream.cc
|
||||||
|
tcponudp/tou.cc
|
||||||
|
tcponudp/udppeer.cc
|
||||||
|
tcponudp/bss_tou.cc
|
||||||
|
tcponudp/udprelay.cc )
|
||||||
|
|
||||||
|
if(RS_BITDHT_STUNNER)
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
tcponudp/udpstunner.cc )
|
||||||
|
endif(RS_BITDHT_STUNNER)
|
||||||
|
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
turtle/rsturtleitem.cc
|
||||||
|
turtle/p3turtle.cc )
|
||||||
|
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
# util/contentvalue.cc
|
||||||
|
# util/exampletst.c
|
||||||
|
# util/rsdbbind.cc
|
||||||
|
# util/rsdiscspace.cc
|
||||||
|
util/rsexpr.cc
|
||||||
|
util/rsprint.cc
|
||||||
|
# util/rsrecogn.cc
|
||||||
|
# util/rssharedptr.h
|
||||||
|
# util/rstickevent.cc
|
||||||
|
util/rstime.cc
|
||||||
|
util/smallobject.cc
|
||||||
|
# util/retrodb.cc
|
||||||
|
util/rsbase64.cc
|
||||||
|
util/rsjson.cc
|
||||||
|
# util/rskbdinput.cc
|
||||||
|
util/rsrandom.cc
|
||||||
|
util/rsstring.cc
|
||||||
|
util/rsurl.cc
|
||||||
|
util/folderiterator.cc
|
||||||
|
util/rsdir.cc
|
||||||
|
util/dnsresolver.cc
|
||||||
|
util/extaddrfinder.cc
|
||||||
|
util/rsdebug.cc
|
||||||
|
util/rsdnsutils.cc
|
||||||
|
util/rsnet.cc
|
||||||
|
util/rsnet_ss.cc
|
||||||
|
util/rsthreads.cc )
|
||||||
|
|
||||||
|
# util/i2pcommon.cpp
|
||||||
|
# util/i2pcommon.h
|
||||||
|
|
||||||
|
if(RS_FORUM_DEEP_INDEX)
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
deep_search/commonutils.cpp
|
||||||
|
deep_search/forumsindex.cpp )
|
||||||
|
endif(RS_FORUM_DEEP_INDEX)
|
||||||
|
|
||||||
|
|
||||||
|
#./deep_search/filesflacindexer.hpp
|
||||||
|
#./deep_search/filesoggindexer.hpp
|
||||||
|
#./deep_search/filestaglibindexer.hpp
|
||||||
|
#./deep_search/filesindex.cpp
|
||||||
|
#./deep_search/filesindex.hpp
|
||||||
|
#./deep_search/channelsindex.cpp
|
||||||
|
#./deep_search/channelsindex.hpp
|
||||||
|
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
gossipdiscovery/gossipdiscoveryitems.cc
|
||||||
|
gossipdiscovery/p3gossipdiscovery.cc )
|
||||||
|
|
||||||
|
if(RS_MINIUPNPC)
|
||||||
|
list(
|
||||||
|
APPEND RS_SOURCES
|
||||||
|
rs_upnp/upnphandler_miniupnp.cc )
|
||||||
|
endif(RS_MINIUPNPC)
|
||||||
|
|
||||||
|
#./rs_upnp/UPnPBase.cpp
|
||||||
|
#./rs_upnp/upnphandler_libupnp.cc
|
||||||
|
#./rs_upnp/upnptest.cc
|
||||||
|
#./rs_upnp/upnputil.cc
|
||||||
|
|
||||||
|
#./rs_android/LocalArray.h
|
||||||
|
#./rs_android/README-ifaddrs-android.adoc
|
||||||
|
#./rs_android/ScopedFd.h
|
||||||
|
#./rs_android/androidcoutcerrcatcher.hpp
|
||||||
|
#./rs_android/errorconditionwrap.cpp
|
||||||
|
#./rs_android/ifaddrs-android.h
|
||||||
|
#./rs_android/org
|
||||||
|
#./rs_android/org/retroshare
|
||||||
|
#./rs_android/org/retroshare/service
|
||||||
|
#./rs_android/org/retroshare/service/AssetHelper.java
|
||||||
|
#./rs_android/org/retroshare/service/ErrorConditionWrap.java
|
||||||
|
#./rs_android/org/retroshare/service/RetroShareServiceAndroid.java
|
||||||
|
#./rs_android/retroshareserviceandroid.cpp
|
||||||
|
#./rs_android/retroshareserviceandroid.hpp
|
||||||
|
#./rs_android/rsjni.cpp
|
||||||
|
#./rs_android/rsjni.hpp
|
|
@ -46,7 +46,9 @@ std::error_condition DeepForumsIndex::search(
|
||||||
// End of prefix configuration.
|
// End of prefix configuration.
|
||||||
|
|
||||||
// And parse the query.
|
// And parse the query.
|
||||||
Xapian::Query query = queryparser.parse_query(queryStr);
|
using XQP = Xapian::QueryParser;
|
||||||
|
Xapian::Query query = queryparser.parse_query(
|
||||||
|
queryStr, XQP::FLAG_WILDCARD | XQP::FLAG_DEFAULT );
|
||||||
|
|
||||||
// Use an Enquire object on the database to run the query.
|
// Use an Enquire object on the database to run the query.
|
||||||
Xapian::Enquire enquire(db);
|
Xapian::Enquire enquire(db);
|
||||||
|
|
|
@ -107,7 +107,7 @@ p3discovery2::p3discovery2(
|
||||||
addSerialType(new RsDiscSerialiser());
|
addSerialType(new RsDiscSerialiser());
|
||||||
|
|
||||||
// Add self into PGP FriendList.
|
// Add self into PGP FriendList.
|
||||||
mFriendList[AuthGPG::getAuthGPG()->getGPGOwnId()] = DiscPgpInfo();
|
mFriendList[AuthPGP::getPgpOwnId()] = DiscPgpInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@ void p3discovery2::removeFriend(const RsPeerId &sslId)
|
||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
#endif
|
#endif
|
||||||
/* pgp peer without any ssl entries -> check if they are still a real friend */
|
/* pgp peer without any ssl entries -> check if they are still a real friend */
|
||||||
if (!(AuthGPG::getAuthGPG()->isGPGAccepted(pgpId)))
|
if (!(AuthPGP::isPGPAccepted(pgpId)))
|
||||||
{
|
{
|
||||||
#ifdef P3DISC_DEBUG
|
#ifdef P3DISC_DEBUG
|
||||||
std::cerr << "p3discovery2::addFriend() pgpId is no longer a friend, removing";
|
std::cerr << "p3discovery2::addFriend() pgpId is no longer a friend, removing";
|
||||||
|
@ -604,8 +604,8 @@ void p3discovery2::updatePgpFriendList()
|
||||||
std::list<RsPgpId>::iterator lit;
|
std::list<RsPgpId>::iterator lit;
|
||||||
std::map<RsPgpId, DiscPgpInfo>::iterator it;
|
std::map<RsPgpId, DiscPgpInfo>::iterator it;
|
||||||
|
|
||||||
RsPgpId ownPgpId = AuthGPG::getAuthGPG()->getGPGOwnId();
|
RsPgpId ownPgpId = AuthPGP::getPgpOwnId();
|
||||||
AuthGPG::getAuthGPG()->getGPGAcceptedList(pgpList);
|
AuthPGP::getPgpAcceptedList(pgpList);
|
||||||
pgpList.push_back(ownPgpId);
|
pgpList.push_back(ownPgpId);
|
||||||
|
|
||||||
// convert to set for ordering.
|
// convert to set for ordering.
|
||||||
|
@ -723,7 +723,7 @@ void p3discovery2::processPGPList(const RsPeerId &fromId, const RsDiscPgpListIte
|
||||||
std::set<RsPgpId>::const_iterator fit;
|
std::set<RsPgpId>::const_iterator fit;
|
||||||
for(fit = item->pgpIdSet.ids.begin(); fit != item->pgpIdSet.ids.end(); ++fit)
|
for(fit = item->pgpIdSet.ids.begin(); fit != item->pgpIdSet.ids.end(); ++fit)
|
||||||
{
|
{
|
||||||
if (!AuthGPG::getAuthGPG()->isGPGId(*fit))
|
if (!AuthPGP::isPGPId(*fit))
|
||||||
{
|
{
|
||||||
#ifdef P3DISC_DEBUG
|
#ifdef P3DISC_DEBUG
|
||||||
std::cerr << "p3discovery2::processPGPList() requesting certificate for PgpId: " << *fit;
|
std::cerr << "p3discovery2::processPGPList() requesting certificate for PgpId: " << *fit;
|
||||||
|
@ -1058,11 +1058,11 @@ void p3discovery2::recvPGPCertificateRequest( const RsPeerId& fromId, const RsDi
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RsPgpId ownPgpId = AuthGPG::getAuthGPG()->getGPGOwnId();
|
RsPgpId ownPgpId = AuthPGP::getPgpOwnId();
|
||||||
for(const RsPgpId& pgpId : item->pgpIdSet.ids)
|
for(const RsPgpId& pgpId : item->pgpIdSet.ids)
|
||||||
if (pgpId == ownPgpId)
|
if (pgpId == ownPgpId)
|
||||||
sendPGPCertificate(pgpId, fromId);
|
sendPGPCertificate(pgpId, fromId);
|
||||||
else if(ps.vs_disc != RS_VS_DISC_OFF && AuthGPG::getAuthGPG()->isGPGAccepted(pgpId))
|
else if(ps.vs_disc != RS_VS_DISC_OFF && AuthPGP::isPGPAccepted(pgpId))
|
||||||
sendPGPCertificate(pgpId, fromId);
|
sendPGPCertificate(pgpId, fromId);
|
||||||
else
|
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;
|
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;
|
||||||
|
@ -1078,7 +1078,7 @@ void p3discovery2::sendPGPCertificate(const RsPgpId &aboutId, const RsPeerId &to
|
||||||
unsigned char *bin_data;
|
unsigned char *bin_data;
|
||||||
size_t bin_len;
|
size_t bin_len;
|
||||||
|
|
||||||
if(!AuthGPG::getAuthGPG()->exportPublicKey(aboutId,bin_data,bin_len,false,true))
|
if(!AuthPGP::exportPublicKey(aboutId,bin_data,bin_len,false,true))
|
||||||
{
|
{
|
||||||
std::cerr << "(EE) cannot export public key " << aboutId << " requested by peer " << toId << std::endl;
|
std::cerr << "(EE) cannot export public key " << aboutId << " requested by peer " << toId << std::endl;
|
||||||
return ;
|
return ;
|
||||||
|
@ -1098,7 +1098,7 @@ void p3discovery2::recvPGPCertificate(const RsPeerId& fromId, RsDiscPgpKeyItem*
|
||||||
std::string cert_name;
|
std::string cert_name;
|
||||||
std::list<RsPgpId> cert_signers;
|
std::list<RsPgpId> cert_signers;
|
||||||
|
|
||||||
if(!AuthGPG::getAuthGPG()->getGPGDetailsFromBinaryBlock( (unsigned char*)item->bin_data,item->bin_len, cert_pgp_id, cert_name, cert_signers ))
|
if(!AuthPGP::getPgpDetailsFromBinaryBlock( (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;
|
std::cerr << "(EE) cannot parse own PGP key sent by " << fromId << std::endl;
|
||||||
return;
|
return;
|
||||||
|
@ -1147,7 +1147,7 @@ void p3discovery2::recvPGPCertificate(const RsPeerId& fromId, RsDiscPgpKeyItem*
|
||||||
// otherwise the connection should already be accepted. This only happens when the short invite peer sends its own PGP key.
|
// 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)
|
if(det.skip_pgp_signature_validation)
|
||||||
AuthGPG::getAuthGPG()->AllowConnection(det.gpg_id,true);
|
AuthPGP::AllowConnection(det.gpg_id,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************* from pqiServiceMonitor *******************/
|
/************* from pqiServiceMonitor *******************/
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "rsserver/p3face.h"
|
#include "rsserver/p3face.h"
|
||||||
#include "retroshare/rsevents.h"
|
#include "retroshare/rsevents.h"
|
||||||
#include "util/radix64.h"
|
#include "util/radix64.h"
|
||||||
|
#include "util/cxx17retrocompat.h"
|
||||||
|
|
||||||
#define PUB_GRP_MASK 0x000f
|
#define PUB_GRP_MASK 0x000f
|
||||||
#define RESTR_GRP_MASK 0x00f0
|
#define RESTR_GRP_MASK 0x00f0
|
||||||
|
@ -2285,8 +2286,9 @@ bool RsGenExchange::processGrpMask(const RsGxsGroupId& grpId, ContentValue &grpC
|
||||||
|
|
||||||
void RsGenExchange::publishMsgs()
|
void RsGenExchange::publishMsgs()
|
||||||
{
|
{
|
||||||
|
bool atLeastOneMessageCreatedSuccessfully = false;
|
||||||
|
|
||||||
RS_STACK_MUTEX(mGenMtx) ;
|
RS_STACK_MUTEX(mGenMtx);
|
||||||
|
|
||||||
rstime_t now = time(NULL);
|
rstime_t now = time(NULL);
|
||||||
|
|
||||||
|
@ -2463,6 +2465,8 @@ void RsGenExchange::publishMsgs()
|
||||||
// add to published to allow acknowledgement
|
// add to published to allow acknowledgement
|
||||||
mMsgNotify.insert(std::make_pair(mit->first, std::make_pair(grpId, msgId)));
|
mMsgNotify.insert(std::make_pair(mit->first, std::make_pair(grpId, msgId)));
|
||||||
mDataAccess->updatePublicRequestStatus(mit->first, RsTokenService::COMPLETE);
|
mDataAccess->updatePublicRequestStatus(mit->first, RsTokenService::COMPLETE);
|
||||||
|
|
||||||
|
atLeastOneMessageCreatedSuccessfully = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2496,6 +2500,8 @@ void RsGenExchange::publishMsgs()
|
||||||
|
|
||||||
mNotifications.push_back(ch);
|
mNotifications.push_back(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(atLeastOneMessageCreatedSuccessfully) mNetService->requestPull();
|
||||||
}
|
}
|
||||||
|
|
||||||
RsGenExchange::ServiceCreate_Return RsGenExchange::service_CreateGroup(RsGxsGrpItem* /* grpItem */,
|
RsGenExchange::ServiceCreate_Return RsGenExchange::service_CreateGroup(RsGxsGrpItem* /* grpItem */,
|
||||||
|
@ -2723,7 +2729,8 @@ bool RsGenExchange::checkKeys(const RsTlvSecurityKeySet& keySet)
|
||||||
|
|
||||||
void RsGenExchange::publishGrps()
|
void RsGenExchange::publishGrps()
|
||||||
{
|
{
|
||||||
std::list<RsGxsGroupId> groups_to_subscribe ;
|
bool atLeastOneGroupCreatedSuccessfully = false;
|
||||||
|
std::list<RsGxsGroupId> groups_to_subscribe;
|
||||||
|
|
||||||
{
|
{
|
||||||
RS_STACK_MUTEX(mGenMtx) ;
|
RS_STACK_MUTEX(mGenMtx) ;
|
||||||
|
@ -2954,6 +2961,8 @@ void RsGenExchange::publishGrps()
|
||||||
|
|
||||||
// add to published to allow acknowledgement
|
// add to published to allow acknowledgement
|
||||||
toNotify.insert(std::make_pair(token, GrpNote(true,ggps.mIsUpdate,grpId)));
|
toNotify.insert(std::make_pair(token, GrpNote(true,ggps.mIsUpdate,grpId)));
|
||||||
|
|
||||||
|
atLeastOneGroupCreatedSuccessfully = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2972,9 +2981,14 @@ void RsGenExchange::publishGrps()
|
||||||
|
|
||||||
// This is done off-mutex to avoid possible cross deadlocks with the net service.
|
// This is done off-mutex to avoid possible cross deadlocks with the net service.
|
||||||
|
|
||||||
if(mNetService!=NULL)
|
if(mNetService != nullptr)
|
||||||
for(std::list<RsGxsGroupId>::const_iterator it(groups_to_subscribe.begin());it!=groups_to_subscribe.end();++it)
|
{
|
||||||
mNetService->subscribeStatusChanged((*it),true) ;
|
for(auto& grpId : std::as_const(groups_to_subscribe))
|
||||||
|
mNetService->subscribeStatusChanged(grpId, true);
|
||||||
|
|
||||||
|
if(atLeastOneGroupCreatedSuccessfully)
|
||||||
|
mNetService->requestPull();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t RsGenExchange::generatePublicToken()
|
uint32_t RsGenExchange::generatePublicToken()
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
// |
|
// |
|
||||||
// +----------- sharePublishKeys()
|
// +----------- sharePublishKeys()
|
||||||
// |
|
// |
|
||||||
// +----------- syncWithPeers()
|
// +----------- checkUpdatesFromPeers()
|
||||||
// | |
|
// | |
|
||||||
// | +--if AutoSync--- send global UpdateTS of each peer to itself => the peer knows the last
|
// | +--if AutoSync--- send global UpdateTS of each peer to itself => the peer knows the last
|
||||||
// | | time current peer has received an updated from himself
|
// | | time current peer has received an updated from himself
|
||||||
|
@ -127,14 +127,14 @@
|
||||||
// (Set at server side to be mGrpServerUpdateItem->grpUpdateTS)
|
// (Set at server side to be mGrpServerUpdateItem->grpUpdateTS)
|
||||||
//
|
//
|
||||||
// Only updated in processCompletedIncomingTransaction() from Grp list transaction.
|
// Only updated in processCompletedIncomingTransaction() from Grp list transaction.
|
||||||
// Used in syncWithPeers() sending in RsNxsSyncGrp once to all peers: peer will send data if
|
// Used in checkUpdatesFromPeers() sending in RsNxsSyncGrp once to all peers: peer will send data if
|
||||||
// has something new. All time comparisons are in the friends' clock time.
|
// has something new. All time comparisons are in the friends' clock time.
|
||||||
//
|
//
|
||||||
// mClientMsgUpdateMap: map< RsPeerId, map<grpId,TimeStamp > >
|
// mClientMsgUpdateMap: map< RsPeerId, map<grpId,TimeStamp > >
|
||||||
//
|
//
|
||||||
// Last msg list modification time sent by that peer Id
|
// Last msg list modification time sent by that peer Id
|
||||||
// Updated in processCompletedIncomingTransaction() from Grp list trans.
|
// Updated in processCompletedIncomingTransaction() from Grp list trans.
|
||||||
// Used in syncWithPeers() sending in RsNxsSyncGrp once to all peers.
|
// Used in checkUpdatesFromPeers() sending in RsNxsSyncGrp once to all peers.
|
||||||
// Set at server to be mServerMsgUpdateMap[grpId]->msgUpdateTS
|
// Set at server to be mServerMsgUpdateMap[grpId]->msgUpdateTS
|
||||||
//
|
//
|
||||||
// mGrpServerUpdateItem: TimeStamp Last group local modification timestamp over all groups
|
// mGrpServerUpdateItem: TimeStamp Last group local modification timestamp over all groups
|
||||||
|
@ -150,7 +150,7 @@
|
||||||
//
|
//
|
||||||
// tick() tick()
|
// tick() tick()
|
||||||
// | |
|
// | |
|
||||||
// +---- SyncWithPeers +-- recvNxsItemQueue()
|
// +---- checkUpdatesFromPeers() +-- recvNxsItemQueue()
|
||||||
// | |
|
// | |
|
||||||
// +---------------- Send global UpdateTS of each peer to itself => the peer knows +---------> +------ handleRecvSyncGroup( RsNxsSyncGrp*)
|
// +---------------- 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
|
// | the last msg sent (stored in mClientGrpUpdateMap[peer_id]), | | - parse all subscribed groups. For each, send a RsNxsSyncGrpItem with publish TS
|
||||||
|
@ -457,7 +457,7 @@ int RsGxsNetService::tick()
|
||||||
|
|
||||||
if((elapsed) < now)
|
if((elapsed) < now)
|
||||||
{
|
{
|
||||||
syncWithPeers();
|
checkUpdatesFromPeers();
|
||||||
syncGrpStatistics();
|
syncGrpStatistics();
|
||||||
checkDistantSyncState();
|
checkDistantSyncState();
|
||||||
|
|
||||||
|
@ -570,22 +570,22 @@ RsGxsGroupId RsGxsNetService::hashGrpId(const RsGxsGroupId& gid,const RsPeerId&
|
||||||
return RsGxsGroupId( RsDirUtil::sha1sum(tmpmem,SIZE).toByteArray() );
|
return RsGxsGroupId( RsDirUtil::sha1sum(tmpmem,SIZE).toByteArray() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void RsGxsNetService::syncWithPeers()
|
std::error_condition RsGxsNetService::checkUpdatesFromPeers(
|
||||||
|
std::set<RsPeerId> peers )
|
||||||
{
|
{
|
||||||
#ifdef NXS_NET_DEBUG_0
|
#ifdef NXS_NET_DEBUG_0
|
||||||
GXSNETDEBUG___ << "RsGxsNetService::syncWithPeers() this=" << (void*)this << ". serviceInfo=" << mServiceInfo << std::endl;
|
RS_DBG("this=", (void*)this, ". serviceInfo=", mServiceInfo);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static RsNxsSerialiser ser(mServType) ; // this is used to estimate bandwidth.
|
/* If specific peers are passed as paramether ask only to them */
|
||||||
|
if(peers.empty())
|
||||||
RS_STACK_MUTEX(mNxsMutex) ;
|
{
|
||||||
|
|
||||||
std::set<RsPeerId> peers;
|
|
||||||
mNetMgr->getOnlineList(mServiceInfo.mServiceType, peers);
|
mNetMgr->getOnlineList(mServiceInfo.mServiceType, peers);
|
||||||
|
|
||||||
if(mAllowDistSync && mGxsNetTunnel != NULL)
|
if(mAllowDistSync && mGxsNetTunnel != nullptr)
|
||||||
{
|
{
|
||||||
// Grab all online virtual peers of distant tunnels for the current service.
|
/* Grab all online virtual peers of distant tunnels for the current
|
||||||
|
* service. */
|
||||||
|
|
||||||
std::list<RsGxsNetTunnelVirtualPeerId> vpids ;
|
std::list<RsGxsNetTunnelVirtualPeerId> vpids ;
|
||||||
mGxsNetTunnel->getVirtualPeers(vpids);
|
mGxsNetTunnel->getVirtualPeers(vpids);
|
||||||
|
@ -593,16 +593,17 @@ void RsGxsNetService::syncWithPeers()
|
||||||
for(auto it(vpids.begin());it!=vpids.end();++it)
|
for(auto it(vpids.begin());it!=vpids.end();++it)
|
||||||
peers.insert(RsPeerId(*it)) ;
|
peers.insert(RsPeerId(*it)) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (peers.empty()) {
|
|
||||||
// nothing to do
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Still empty? Reports there are no available peers
|
||||||
|
if (peers.empty()) return std::errc::network_down;
|
||||||
|
|
||||||
|
|
||||||
|
RS_STACK_MUTEX(mNxsMutex);
|
||||||
|
|
||||||
// for now just grps
|
// for now just grps
|
||||||
for(auto sit = peers.begin(); sit != peers.end(); ++sit)
|
for(auto sit = peers.begin(); sit != peers.end(); ++sit)
|
||||||
{
|
{
|
||||||
|
|
||||||
const RsPeerId peerId = *sit;
|
const RsPeerId peerId = *sit;
|
||||||
|
|
||||||
ClientGrpMap::const_iterator cit = mClientGrpUpdateMap.find(peerId);
|
ClientGrpMap::const_iterator cit = mClientGrpUpdateMap.find(peerId);
|
||||||
|
@ -624,8 +625,7 @@ void RsGxsNetService::syncWithPeers()
|
||||||
generic_sendItem(grp);
|
generic_sendItem(grp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!mAllowMsgSync)
|
if(!mAllowMsgSync) return std::error_condition();
|
||||||
return ;
|
|
||||||
|
|
||||||
#ifndef GXS_DISABLE_SYNC_MSGS
|
#ifndef GXS_DISABLE_SYNC_MSGS
|
||||||
|
|
||||||
|
@ -743,10 +743,12 @@ void RsGxsNetService::syncWithPeers()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif // ndef GXS_DISABLE_SYNC_MSGS
|
||||||
|
|
||||||
|
return std::error_condition();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RsGxsNetService::generic_sendItem(RsNxsItem *si)
|
void RsGxsNetService::generic_sendItem(rs_owner_ptr<RsItem> si)
|
||||||
{
|
{
|
||||||
// check if the item is to be sent to a distant peer or not
|
// check if the item is to be sent to a distant peer or not
|
||||||
|
|
||||||
|
@ -1022,32 +1024,32 @@ void RsGxsNetService::locked_resetClientTS(const RsGxsGroupId& grpId)
|
||||||
it->second.msgUpdateInfos.erase(grpId) ;
|
it->second.msgUpdateInfos.erase(grpId) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RsGxsNetService::subscribeStatusChanged(const RsGxsGroupId& grpId,bool subscribed)
|
void RsGxsNetService::subscribeStatusChanged(
|
||||||
|
const RsGxsGroupId& grpId, bool subscribed )
|
||||||
{
|
{
|
||||||
RS_STACK_MUTEX(mNxsMutex) ;
|
if(!subscribed) return;
|
||||||
|
|
||||||
if(!subscribed)
|
|
||||||
return ;
|
|
||||||
|
|
||||||
// When we subscribe, we reset the time stamps, so that the entire group list
|
// When we subscribe, we reset the time stamps, so that the entire group list
|
||||||
// gets requested once again, for a proper update.
|
// gets requested once again, for a proper update.
|
||||||
|
|
||||||
|
RS_STACK_MUTEX(mNxsMutex);
|
||||||
|
|
||||||
#ifdef NXS_NET_DEBUG_0
|
#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;
|
RS_DBG( "Changing subscribe status for grp", grpId, " to ", subscribed,
|
||||||
std::map<RsGxsGroupId,RsGxsServerMsgUpdate>::iterator it = mServerMsgUpdateMap.find(grpId) ;
|
": reseting all server msg time stamps for this group, and "
|
||||||
|
"server global TS." );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RsGxsServerMsgUpdate& item(mServerMsgUpdateMap[grpId]) ;
|
RsGxsServerMsgUpdate& item(mServerMsgUpdateMap[grpId]);
|
||||||
|
item.msgUpdateTS = static_cast<uint32_t>(time(nullptr));
|
||||||
|
|
||||||
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 = static_cast<uint32_t>(time(nullptr));
|
||||||
|
|
||||||
// We also update mGrpServerUpdateItem so as to trigger a new grp list exchange with friends (friends will send their known ClientTS which
|
locked_resetClientTS(grpId);
|
||||||
// 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
|
bool RsGxsNetService::fragmentMsg(RsNxsMsg& msg, MsgFragments& msgFragments) const
|
||||||
|
@ -1718,13 +1720,25 @@ RsItem *RsGxsNetService::generic_recvItem()
|
||||||
|
|
||||||
void RsGxsNetService::recvNxsItemQueue()
|
void RsGxsNetService::recvNxsItemQueue()
|
||||||
{
|
{
|
||||||
RsItem *item ;
|
RsItem* item;
|
||||||
|
|
||||||
while(NULL != (item=generic_recvItem()))
|
while(nullptr != (item=generic_recvItem()))
|
||||||
{
|
{
|
||||||
#ifdef NXS_NET_DEBUG_1
|
#ifdef NXS_NET_DEBUG_1
|
||||||
GXSNETDEBUG_P_(item->PeerId()) << "Received RsGxsNetService Item:" << (void*)item << " type=" << std::hex << item->PacketId() << std::dec << std::endl ;
|
RS_DBG( "Received RsGxsNetService Item: ", (void*)item, " type=",
|
||||||
|
item->PacketId() );
|
||||||
#endif
|
#endif
|
||||||
|
/* Handle pull request and other new items here to not mess with all the
|
||||||
|
* old nested code and items hell */
|
||||||
|
switch(static_cast<RsNxsSubtype>(item->PacketSubType()))
|
||||||
|
{
|
||||||
|
case RsNxsSubtype::PULL_REQUEST:
|
||||||
|
std::unique_ptr<RsNxsPullRequestItem> pullItem(
|
||||||
|
static_cast<RsNxsPullRequestItem*>(item) );
|
||||||
|
handlePullRequest(std::move(pullItem));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// RsNxsItem needs dynamic_cast, since they have derived siblings.
|
// RsNxsItem needs dynamic_cast, since they have derived siblings.
|
||||||
//
|
//
|
||||||
RsNxsItem *ni = dynamic_cast<RsNxsItem*>(item) ;
|
RsNxsItem *ni = dynamic_cast<RsNxsItem*>(item) ;
|
||||||
|
@ -4690,7 +4704,7 @@ bool RsGxsNetService::checkPermissionsForFriendGroup(const RsPeerId& sslId,const
|
||||||
if(!grpMeta.mInternalCircle.isNull())
|
if(!grpMeta.mInternalCircle.isNull())
|
||||||
{
|
{
|
||||||
RsGroupInfo ginfo ;
|
RsGroupInfo ginfo ;
|
||||||
RsPgpId pgpId = mPgpUtils->getPGPId(sslId) ;
|
RsPgpId pgpId = mPgpUtils->getPgpId(sslId) ;
|
||||||
|
|
||||||
#ifdef NXS_NET_DEBUG_4
|
#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) << " Group internal circle: " << grpMeta.mInternalCircle << ", We're owner. Sending to everyone in the group." << std::endl;
|
||||||
|
@ -5075,6 +5089,46 @@ void RsGxsNetService::handleRecvPublishKeys(RsNxsGroupPublishKeyItem *item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::error_condition RsGxsNetService::requestPull(std::set<RsPeerId> peers)
|
||||||
|
{
|
||||||
|
/* If specific peers are passed as paramether ask only to them */
|
||||||
|
if(peers.empty())
|
||||||
|
{
|
||||||
|
mNetMgr->getOnlineList(mServiceInfo.mServiceType, peers);
|
||||||
|
|
||||||
|
if(mAllowDistSync && mGxsNetTunnel != nullptr)
|
||||||
|
{
|
||||||
|
/* Grab all online virtual peers of distant tunnels for the current
|
||||||
|
* service. */
|
||||||
|
|
||||||
|
std::list<RsGxsNetTunnelVirtualPeerId> vpids ;
|
||||||
|
mGxsNetTunnel->getVirtualPeers(vpids);
|
||||||
|
|
||||||
|
for(auto it(vpids.begin());it!=vpids.end();++it)
|
||||||
|
peers.insert(RsPeerId(*it)) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Still empty? Reports there are no available peers
|
||||||
|
if (peers.empty()) return std::errc::network_down;
|
||||||
|
|
||||||
|
for(auto& peerId: std::as_const(peers))
|
||||||
|
{
|
||||||
|
auto item = new RsNxsPullRequestItem(
|
||||||
|
static_cast<RsServiceType>(mServType) );
|
||||||
|
item->PeerId(peerId);
|
||||||
|
generic_sendItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::error_condition();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RsGxsNetService::handlePullRequest(
|
||||||
|
std::unique_ptr<RsNxsPullRequestItem> item )
|
||||||
|
{
|
||||||
|
checkUpdatesFromPeers(std::set<RsPeerId>{item->PeerId()});
|
||||||
|
}
|
||||||
|
|
||||||
bool RsGxsNetService::getGroupServerUpdateTS(const RsGxsGroupId& gid,rstime_t& group_server_update_TS, rstime_t& msg_server_update_TS)
|
bool RsGxsNetService::getGroupServerUpdateTS(const RsGxsGroupId& gid,rstime_t& group_server_update_TS, rstime_t& msg_server_update_TS)
|
||||||
{
|
{
|
||||||
RS_STACK_MUTEX(mNxsMutex) ;
|
RS_STACK_MUTEX(mNxsMutex) ;
|
||||||
|
|
|
@ -250,6 +250,15 @@ public:
|
||||||
|
|
||||||
void threadTick() override; /// @see RsTickingThread
|
void threadTick() override; /// @see RsTickingThread
|
||||||
|
|
||||||
|
|
||||||
|
/// @see RsNetworkExchangeService
|
||||||
|
std::error_condition checkUpdatesFromPeers(
|
||||||
|
std::set<RsPeerId> peers = std::set<RsPeerId>() ) override;
|
||||||
|
|
||||||
|
/// @see RsNetworkExchangeService
|
||||||
|
std::error_condition requestPull(
|
||||||
|
std::set<RsPeerId> peers = std::set<RsPeerId>() ) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -423,6 +432,8 @@ private:
|
||||||
*/
|
*/
|
||||||
void handleRecvPublishKeys(RsNxsGroupPublishKeyItem*) ;
|
void handleRecvPublishKeys(RsNxsGroupPublishKeyItem*) ;
|
||||||
|
|
||||||
|
void handlePullRequest(std::unique_ptr<RsNxsPullRequestItem> item);
|
||||||
|
|
||||||
/** E: item handlers **/
|
/** E: item handlers **/
|
||||||
|
|
||||||
|
|
||||||
|
@ -459,7 +470,7 @@ private:
|
||||||
void locked_pushMsgRespFromList(std::list<RsNxsItem*>& itemL, const RsPeerId& sslId, const RsGxsGroupId &grp_id, const uint32_t& transN);
|
void locked_pushMsgRespFromList(std::list<RsNxsItem*>& itemL, const RsPeerId& sslId, const RsGxsGroupId &grp_id, const uint32_t& transN);
|
||||||
|
|
||||||
void checkDistantSyncState();
|
void checkDistantSyncState();
|
||||||
void syncWithPeers();
|
|
||||||
void syncGrpStatistics();
|
void syncGrpStatistics();
|
||||||
void addGroupItemToList(NxsTransaction*& tr,
|
void addGroupItemToList(NxsTransaction*& tr,
|
||||||
const RsGxsGroupId& grpId, uint32_t& transN,
|
const RsGxsGroupId& grpId, uint32_t& transN,
|
||||||
|
@ -559,7 +570,7 @@ private:
|
||||||
void cleanRejectedMessages();
|
void cleanRejectedMessages();
|
||||||
void processObserverNotifications();
|
void processObserverNotifications();
|
||||||
|
|
||||||
void generic_sendItem(RsNxsItem *si);
|
void generic_sendItem(rs_owner_ptr<RsItem> si);
|
||||||
RsItem *generic_recvItem();
|
RsItem *generic_recvItem();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -223,7 +223,7 @@ bool GrpCircleVetting::canSend(
|
||||||
{
|
{
|
||||||
if(mCircles->isLoaded(circleId))
|
if(mCircles->isLoaded(circleId))
|
||||||
{
|
{
|
||||||
const RsPgpId& pgpId = mPgpUtils->getPGPId(peerId);
|
const RsPgpId& pgpId = mPgpUtils->getPgpId(peerId);
|
||||||
return mCircles->canSend(circleId, pgpId,should_encrypt);
|
return mCircles->canSend(circleId, pgpId,should_encrypt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,7 +302,7 @@ bool MsgCircleIdsRequestVetting::cleared()
|
||||||
if(filtered_out_msgs>0)
|
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;
|
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);
|
RsPgpId pgpId = mPgpUtils->getPgpId(mPeerId);
|
||||||
bool can_send_res = mCircles->canSend(mCircleId, pgpId,mShouldEncrypt);
|
bool can_send_res = mCircles->canSend(mCircleId, pgpId,mShouldEncrypt);
|
||||||
|
|
||||||
if(mShouldEncrypt) // that means the circle is external
|
if(mShouldEncrypt) // that means the circle is external
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <stdlib.h>
|
#include <cstdlib>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
@ -325,4 +325,20 @@ public:
|
||||||
return RsReputationLevel::NEUTRAL;
|
return RsReputationLevel::NEUTRAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if new stuff is available from peers
|
||||||
|
* @param peers peers to check, if empty all available peers are checked
|
||||||
|
*/
|
||||||
|
virtual std::error_condition checkUpdatesFromPeers(
|
||||||
|
std::set<RsPeerId> peers = std::set<RsPeerId>() ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief request online peers to pull updates from our node ASAP
|
||||||
|
* @param peers peers to which request pull from, if empty all available
|
||||||
|
* peers are requested to pull
|
||||||
|
* @return success or error details
|
||||||
|
*/
|
||||||
|
virtual std::error_condition requestPull(
|
||||||
|
std::set<RsPeerId> peers = std::set<RsPeerId>() ) = 0;
|
||||||
};
|
};
|
||||||
|
|
447
libretroshare/src/jsonapi/README.adoc
Normal file
447
libretroshare/src/jsonapi/README.adoc
Normal file
|
@ -0,0 +1,447 @@
|
||||||
|
// SPDX-FileCopyrightText: (C) 2004-2019 Retroshare Team <contact@retroshare.cc>
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
RetroShare JSON API
|
||||||
|
===================
|
||||||
|
|
||||||
|
:Cxx: C++
|
||||||
|
|
||||||
|
== 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<std::string>+. 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<void (const RsGxsGroupSummary& result)>& 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<void (...)>+ 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
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* RetroShare JSON API *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
|
* *
|
||||||
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU 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 <https://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
registerHandler( "$%apiPath%$",
|
||||||
|
[this](const std::shared_ptr<rb::Session> session)
|
||||||
|
{
|
||||||
|
const std::multimap<std::string, std::string> 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<rb::Session> session,
|
||||||
|
const rb::Bytes& body )
|
||||||
|
{
|
||||||
|
INITIALIZE_API_CALL_JSON_CONTEXT;
|
||||||
|
|
||||||
|
if( !checkRsServicePtrReady(
|
||||||
|
$%instanceName%$, "$%instanceName%$", cAns, session ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
$%paramsDeclaration%$
|
||||||
|
|
||||||
|
$%inputParamsDeserialization%$
|
||||||
|
|
||||||
|
const std::weak_ptr<rb::Service> weakService(mService);
|
||||||
|
const std::weak_ptr<rb::Session> 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%$ );
|
230
libretroshare/src/jsonapi/jsonapi-generator-doxygen.conf
Normal file
230
libretroshare/src/jsonapi/jsonapi-generator-doxygen.conf
Normal file
|
@ -0,0 +1,230 @@
|
||||||
|
DOXYFILE_ENCODING = UTF-8
|
||||||
|
PROJECT_NAME = "libretroshare"
|
||||||
|
|
||||||
|
ALIASES += jsonapi{1}="\xmlonly<jsonapi minversion=\"\1\"/>\endxmlonly"
|
||||||
|
ALIASES += jsonapi{2}="\xmlonly<jsonapi minversion=\"\1\" access=\"\2\"/>\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
|
||||||
|
|
365
libretroshare/src/jsonapi/jsonapi-generator.py
Executable file
365
libretroshare/src/jsonapi/jsonapi-generator.py
Executable file
|
@ -0,0 +1,365 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
# RetroShare JSON API generator
|
||||||
|
#
|
||||||
|
# Copyright (C) 2019 selankon <selankon@selankon.xyz>
|
||||||
|
# Copyright (C) 2021 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||||
|
# Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify it under
|
||||||
|
# the terms of the GNU Affero General Public License as published by the
|
||||||
|
# Free Software Foundation, 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 <https://www.gnu.org/licenses/>
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: Retroshare Team <contact@retroshare.cc>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
|
||||||
|
# Original idea and implementation by G10h4ck (jsonapi-generator.cpp)
|
||||||
|
# Initial python reimplementation by Sehraf
|
||||||
|
#
|
||||||
|
# This python 3 script has superseded the original C++/Qt implementation this
|
||||||
|
# and is now used at build time in without depending on Qt.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
from string import Template
|
||||||
|
|
||||||
|
|
||||||
|
class MethodParam:
|
||||||
|
_type = ''
|
||||||
|
_name = ''
|
||||||
|
_defval = ''
|
||||||
|
_in = False
|
||||||
|
_out = False
|
||||||
|
_isMultiCallback = False
|
||||||
|
_isSingleCallback = False
|
||||||
|
|
||||||
|
|
||||||
|
class TemplateOwn(Template):
|
||||||
|
delimiter = '$%'
|
||||||
|
pattern = '''
|
||||||
|
\$%(?:
|
||||||
|
(?P<escaped>\$\%) | # Escape sequence of two delimiters
|
||||||
|
(?P<named>[_a-z][_a-z0-9]*)%\$ | # delimiter and a Python identifier
|
||||||
|
{(?P<braced>[_a-z][_a-z0-9]*)} | # delimiter and a braced identifier
|
||||||
|
(?P<invalid>) # Other ill-formed delimiter exprs
|
||||||
|
)
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
def getText(e):
|
||||||
|
return "".join(e.itertext())
|
||||||
|
|
||||||
|
|
||||||
|
def processFile(file):
|
||||||
|
try:
|
||||||
|
dom1 = ET.parse(file).getroot()
|
||||||
|
except FileNotFoundError:
|
||||||
|
print('Can\'t open:', file)
|
||||||
|
|
||||||
|
headerFileInfo = dom1[0].findall('location')[0].attrib['file']
|
||||||
|
headerRelPath = os.path.dirname(headerFileInfo).split('/')[-1] + '/' + os.path.basename(headerFileInfo)
|
||||||
|
|
||||||
|
for sectDef in dom1.findall('.//memberdef'):
|
||||||
|
if sectDef.attrib['kind'] != 'variable' or sectDef.find('.//jsonapi') == None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
instanceName = sectDef.find('name').text
|
||||||
|
typeName = sectDef.find('type/ref').text
|
||||||
|
|
||||||
|
typeFilePath = sectDef.find('type/ref').attrib['refid']
|
||||||
|
|
||||||
|
try:
|
||||||
|
dom2 = ET.parse(doxPrefix + typeFilePath + '.xml').getroot()
|
||||||
|
except FileNotFoundError:
|
||||||
|
print('Can\'t open:', doxPrefix + typeFilePath + '.xml')
|
||||||
|
|
||||||
|
for member in dom2.findall('.//member'):
|
||||||
|
refid = member.attrib['refid']
|
||||||
|
methodName = member.find('name').text
|
||||||
|
|
||||||
|
requiresAuth = True
|
||||||
|
|
||||||
|
defFilePath = refid.split('_')[0] + '.xml'
|
||||||
|
defFile = defFilePath
|
||||||
|
|
||||||
|
print('Looking for', typeName, methodName, 'into', typeFilePath)
|
||||||
|
|
||||||
|
try:
|
||||||
|
defDoc = ET.parse(doxPrefix + defFilePath).getroot()
|
||||||
|
except FileNotFoundError:
|
||||||
|
print('Can\'t open:', doxPrefix + defFilePath)
|
||||||
|
|
||||||
|
memberdef = None
|
||||||
|
for tmpMBD in defDoc.findall('.//memberdef'):
|
||||||
|
tmpId = tmpMBD.attrib['id']
|
||||||
|
tmpKind = tmpMBD.attrib['kind']
|
||||||
|
tmpJsonApiTagList = tmpMBD.findall('.//jsonapi')
|
||||||
|
|
||||||
|
if len(tmpJsonApiTagList) != 0 and tmpId == refid and tmpKind == 'function':
|
||||||
|
tmpJsonApiTag = tmpJsonApiTagList[0]
|
||||||
|
|
||||||
|
tmpAccessValue = None
|
||||||
|
if 'access' in tmpJsonApiTag.attrib:
|
||||||
|
tmpAccessValue = tmpJsonApiTag.attrib['access']
|
||||||
|
|
||||||
|
requiresAuth = 'unauthenticated' != tmpAccessValue;
|
||||||
|
|
||||||
|
if 'manualwrapper' != tmpAccessValue:
|
||||||
|
memberdef = tmpMBD
|
||||||
|
|
||||||
|
break
|
||||||
|
|
||||||
|
if memberdef == None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
apiPath = '/' + instanceName + '/' + methodName
|
||||||
|
|
||||||
|
retvalType = getText(memberdef.find('type'))
|
||||||
|
# Apparently some xml declarations include new lines ('\n') and/or multiple spaces
|
||||||
|
# Strip them using python magic
|
||||||
|
retvalType = ' '.join(retvalType.split())
|
||||||
|
|
||||||
|
paramsMap = {}
|
||||||
|
orderedParamNames = []
|
||||||
|
|
||||||
|
hasInput = False
|
||||||
|
hasOutput = False
|
||||||
|
hasSingleCallback = False
|
||||||
|
hasMultiCallback = False
|
||||||
|
callbackName = ''
|
||||||
|
callbackParams = ''
|
||||||
|
|
||||||
|
for tmpPE in memberdef.findall('param'):
|
||||||
|
mp = MethodParam()
|
||||||
|
|
||||||
|
pName = getText(tmpPE.find('declname'))
|
||||||
|
tmpDefval = tmpPE.find('defval')
|
||||||
|
mp._defval = getText(tmpDefval) if tmpDefval != None else ''
|
||||||
|
pType = getText(tmpPE.find('type'))
|
||||||
|
|
||||||
|
if pType.startswith('const '): pType = pType[6:]
|
||||||
|
if pType.startswith('std::function'):
|
||||||
|
if pType.endswith('&'): pType = pType[:-1]
|
||||||
|
if pName.startswith('multiCallback'):
|
||||||
|
mp._isMultiCallback = True
|
||||||
|
hasMultiCallback = True
|
||||||
|
elif pName.startswith('callback'):
|
||||||
|
mp._isSingleCallback = True
|
||||||
|
hasSingleCallback = True
|
||||||
|
callbackName = pName
|
||||||
|
callbackParams = pType
|
||||||
|
else:
|
||||||
|
pType = pType.replace('&', '').replace(' ', '')
|
||||||
|
|
||||||
|
# Apparently some xml declarations include new lines ('\n') and/or multiple spaces
|
||||||
|
# Strip them using python magic
|
||||||
|
pType = ' '.join(pType.split())
|
||||||
|
mp._defval = ' '.join(mp._defval.split())
|
||||||
|
|
||||||
|
mp._type = pType
|
||||||
|
mp._name = pName
|
||||||
|
|
||||||
|
paramsMap[pName] = mp
|
||||||
|
orderedParamNames.append(pName)
|
||||||
|
|
||||||
|
for tmpPN in memberdef.findall('.//parametername'):
|
||||||
|
tmpParam = paramsMap[tmpPN.text]
|
||||||
|
tmpD = tmpPN.attrib['direction'] if 'direction' in tmpPN.attrib else ''
|
||||||
|
|
||||||
|
if 'in' in tmpD:
|
||||||
|
tmpParam._in = True
|
||||||
|
hasInput = True
|
||||||
|
if 'out' in tmpD:
|
||||||
|
tmpParam._out = True
|
||||||
|
hasOutput = True
|
||||||
|
|
||||||
|
# Params sanity check
|
||||||
|
for pmKey in paramsMap:
|
||||||
|
pm = paramsMap[pmKey]
|
||||||
|
if not (pm._isMultiCallback or pm._isSingleCallback or pm._in or pm._out):
|
||||||
|
print('ERROR', 'Parameter:', pm._name, 'of:', apiPath,
|
||||||
|
'declared in:', headerRelPath,
|
||||||
|
'miss doxygen parameter direction attribute!',
|
||||||
|
defFile)
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
functionCall = '\t\t'
|
||||||
|
if retvalType != 'void':
|
||||||
|
functionCall += retvalType + ' retval = '
|
||||||
|
hasOutput = True
|
||||||
|
functionCall += instanceName + '->' + methodName + '('
|
||||||
|
functionCall += ', '.join(orderedParamNames) + ');\n'
|
||||||
|
|
||||||
|
print(instanceName, apiPath, retvalType, typeName, methodName)
|
||||||
|
for pn in orderedParamNames:
|
||||||
|
mp = paramsMap[pn]
|
||||||
|
print('\t', mp._type, mp._name, mp._in, mp._out)
|
||||||
|
|
||||||
|
inputParamsDeserialization = ''
|
||||||
|
if hasInput:
|
||||||
|
inputParamsDeserialization += '\t\t{\n'
|
||||||
|
inputParamsDeserialization += '\t\t\tRsGenericSerializer::SerializeContext& ctx(cReq);\n'
|
||||||
|
inputParamsDeserialization += '\t\t\tRsGenericSerializer::SerializeJob j(RsGenericSerializer::FROM_JSON);\n';
|
||||||
|
|
||||||
|
outputParamsSerialization = ''
|
||||||
|
if hasOutput:
|
||||||
|
outputParamsSerialization += '\t\t{\n'
|
||||||
|
outputParamsSerialization += '\t\t\tRsGenericSerializer::SerializeContext& ctx(cAns);\n'
|
||||||
|
outputParamsSerialization += '\t\t\tRsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON);\n';
|
||||||
|
|
||||||
|
paramsDeclaration = ''
|
||||||
|
for pn in orderedParamNames:
|
||||||
|
mp = paramsMap[pn]
|
||||||
|
paramsDeclaration += '\t\t' + mp._type + ' ' + mp._name
|
||||||
|
if mp._defval != '':
|
||||||
|
paramsDeclaration += ' = ' + mp._defval
|
||||||
|
paramsDeclaration += ';\n'
|
||||||
|
if mp._in:
|
||||||
|
inputParamsDeserialization += '\t\t\tRS_SERIAL_PROCESS('
|
||||||
|
inputParamsDeserialization += mp._name + ');\n'
|
||||||
|
if mp._out:
|
||||||
|
outputParamsSerialization += '\t\t\tRS_SERIAL_PROCESS('
|
||||||
|
outputParamsSerialization += mp._name + ');\n'
|
||||||
|
|
||||||
|
if hasInput:
|
||||||
|
inputParamsDeserialization += '\t\t}\n'
|
||||||
|
if retvalType != 'void':
|
||||||
|
outputParamsSerialization += '\t\t\tRS_SERIAL_PROCESS(retval);\n'
|
||||||
|
if hasOutput:
|
||||||
|
outputParamsSerialization += '\t\t}\n'
|
||||||
|
|
||||||
|
captureVars = ''
|
||||||
|
|
||||||
|
sessionEarlyClose = ''
|
||||||
|
if hasSingleCallback:
|
||||||
|
sessionEarlyClose = 'session->close();'
|
||||||
|
|
||||||
|
sessionDelayedClose = ''
|
||||||
|
if hasMultiCallback:
|
||||||
|
sessionDelayedClose = """
|
||||||
|
RsThread::async( [=]()
|
||||||
|
{
|
||||||
|
std::this_thread::sleep_for(
|
||||||
|
std::chrono::seconds(maxWait+120) );
|
||||||
|
auto lService = weakService.lock();
|
||||||
|
if(!lService || lService->is_down()) return;
|
||||||
|
lService->schedule( [=]()
|
||||||
|
{
|
||||||
|
auto session = weakSession.lock();
|
||||||
|
if(session && session->is_open())
|
||||||
|
session->close();
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
"""
|
||||||
|
captureVars = 'this'
|
||||||
|
|
||||||
|
callbackParamsSerialization = ''
|
||||||
|
|
||||||
|
if hasSingleCallback or hasMultiCallback or (callbackParams.find('(') + 2 < callbackParams.find(')')):
|
||||||
|
cbs = ''
|
||||||
|
|
||||||
|
callbackParams = callbackParams.split('(')[1]
|
||||||
|
callbackParams = callbackParams.split(')')[0]
|
||||||
|
|
||||||
|
cbs += '\t\t\tRsGenericSerializer::SerializeContext ctx;\n'
|
||||||
|
|
||||||
|
for cbPar in callbackParams.split(','):
|
||||||
|
isConst = cbPar.startswith('const ')
|
||||||
|
pSep = ' '
|
||||||
|
isRef = '&' in cbPar
|
||||||
|
if isRef: pSep = '&'
|
||||||
|
sepIndex = cbPar.rfind(pSep) + 1
|
||||||
|
cpt = cbPar[0:sepIndex][6:]
|
||||||
|
cpn = cbPar[sepIndex:]
|
||||||
|
|
||||||
|
cbs += '\t\t\tRsTypeSerializer::serial_process('
|
||||||
|
cbs += 'RsGenericSerializer::TO_JSON, ctx, '
|
||||||
|
if isConst:
|
||||||
|
cbs += 'const_cast<'
|
||||||
|
cbs += cpt
|
||||||
|
cbs += '>('
|
||||||
|
cbs += cpn
|
||||||
|
if isConst: cbs += ')'
|
||||||
|
cbs += ', "'
|
||||||
|
cbs += cpn
|
||||||
|
cbs += '" );\n'
|
||||||
|
|
||||||
|
callbackParamsSerialization += cbs
|
||||||
|
|
||||||
|
substitutionsMap = dict()
|
||||||
|
substitutionsMap['paramsDeclaration'] = paramsDeclaration
|
||||||
|
substitutionsMap['inputParamsDeserialization'] = inputParamsDeserialization
|
||||||
|
substitutionsMap['outputParamsSerialization'] = outputParamsSerialization
|
||||||
|
substitutionsMap['instanceName'] = instanceName
|
||||||
|
substitutionsMap['functionCall'] = functionCall
|
||||||
|
substitutionsMap['apiPath'] = apiPath
|
||||||
|
substitutionsMap['sessionEarlyClose'] = sessionEarlyClose
|
||||||
|
substitutionsMap['sessionDelayedClose'] = sessionDelayedClose
|
||||||
|
substitutionsMap['captureVars'] = captureVars
|
||||||
|
substitutionsMap['callbackName'] = callbackName
|
||||||
|
substitutionsMap['callbackParams'] = callbackParams
|
||||||
|
substitutionsMap['callbackParamsSerialization'] = callbackParamsSerialization
|
||||||
|
substitutionsMap['requiresAuth'] = 'true' if requiresAuth else 'false'
|
||||||
|
|
||||||
|
# print(substitutionsMap)
|
||||||
|
|
||||||
|
templFilePath = sourcePath
|
||||||
|
if hasMultiCallback or hasSingleCallback:
|
||||||
|
templFilePath += '/async-method-wrapper-template.cpp.tmpl'
|
||||||
|
else:
|
||||||
|
templFilePath += '/method-wrapper-template.cpp.tmpl'
|
||||||
|
|
||||||
|
templFile = open(templFilePath, 'r')
|
||||||
|
wrapperDef = TemplateOwn(templFile.read())
|
||||||
|
|
||||||
|
tmp = wrapperDef.substitute(substitutionsMap)
|
||||||
|
wrappersDefFile.write(tmp)
|
||||||
|
|
||||||
|
cppApiIncludesSet.add('#include "' + headerRelPath + '"\n')
|
||||||
|
|
||||||
|
|
||||||
|
if len(sys.argv) != 3:
|
||||||
|
print('Usage:', sys.argv[0], 'SOURCE_PATH OUTPUT_PATH Got:', sys.argv[:])
|
||||||
|
sys.exit(-1)
|
||||||
|
|
||||||
|
sourcePath = str(sys.argv[1])
|
||||||
|
outputPath = str(sys.argv[2])
|
||||||
|
doxPrefix = outputPath + '/xml/'
|
||||||
|
|
||||||
|
try:
|
||||||
|
wrappersDefFile = open(outputPath + '/jsonapi-wrappers.inl', 'w')
|
||||||
|
except FileNotFoundError:
|
||||||
|
print('Can\'t open:', outputPath + '/jsonapi-wrappers.inl')
|
||||||
|
|
||||||
|
try:
|
||||||
|
cppApiIncludesFile = open(outputPath + '/jsonapi-includes.inl', 'w');
|
||||||
|
except FileNotFoundError:
|
||||||
|
print('Can\'t open:', outputPath + '/jsonapi-includes.inl')
|
||||||
|
|
||||||
|
cppApiIncludesSet = set()
|
||||||
|
|
||||||
|
filesIterator = None
|
||||||
|
try:
|
||||||
|
filesIterator = os.listdir(doxPrefix)
|
||||||
|
except FileNotFoundError:
|
||||||
|
print("Doxygen xml output dir not found: ", doxPrefix)
|
||||||
|
os.exit(-1)
|
||||||
|
|
||||||
|
for file in filesIterator:
|
||||||
|
if file.endswith("8h.xml"):
|
||||||
|
processFile(os.path.join(doxPrefix, file))
|
||||||
|
|
||||||
|
|
||||||
|
for incl in cppApiIncludesSet:
|
||||||
|
cppApiIncludesFile.write(incl)
|
|
@ -796,8 +796,9 @@ void JsonApiServer::run()
|
||||||
}
|
}
|
||||||
catch(std::exception& e)
|
catch(std::exception& e)
|
||||||
{
|
{
|
||||||
RsErr() << __PRETTY_FUNCTION__ << " Failure starting JSON API server: "
|
/* TODO: find a way to report back programmatically if failed listening
|
||||||
<< e.what() << std::endl;
|
* port */
|
||||||
|
RS_ERR("Failure starting JSON API server: ", e.what());
|
||||||
print_stacktrace();
|
print_stacktrace();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
50
libretroshare/src/jsonapi/method-wrapper-template.cpp.tmpl
Normal file
50
libretroshare/src/jsonapi/method-wrapper-template.cpp.tmpl
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* RetroShare JSON API *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
|
* *
|
||||||
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU Affero General Public License as *
|
||||||
|
* published by the Free Software Foundation, either version 3 of the *
|
||||||
|
* License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU Affero General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Affero General Public License *
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
registerHandler( "$%apiPath%$",
|
||||||
|
[](const std::shared_ptr<rb::Session> session)
|
||||||
|
{
|
||||||
|
size_t reqSize = session->get_request()->get_header("Content-Length", 0);
|
||||||
|
session->fetch( reqSize, [](
|
||||||
|
const std::shared_ptr<rb::Session> 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%$ );
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# SPDX-FileCopyrightText: (C) 2004-2019 Retroshare Team <contact@retroshare.cc>
|
# SPDX-FileCopyrightText: (C) 2004-2021 Retroshare Team <contact@retroshare.cc>
|
||||||
# SPDX-License-Identifier: CC0-1.0
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
!include("../../retroshare.pri"): error("Could not include file ../../retroshare.pri")
|
!include("../../retroshare.pri"): error("Could not include file ../../retroshare.pri")
|
||||||
|
@ -207,7 +207,7 @@ linux-* {
|
||||||
LIBS *= -ldl
|
LIBS *= -ldl
|
||||||
|
|
||||||
DEFINES *= PLUGIN_DIR=\"\\\"$${PLUGIN_DIR}\\\"\"
|
DEFINES *= PLUGIN_DIR=\"\\\"$${PLUGIN_DIR}\\\"\"
|
||||||
DEFINES *= DATA_DIR=\"\\\"$${DATA_DIR}\\\"\"
|
DEFINES *= RS_DATA_DIR=\"\\\"$${RS_DATA_DIR}\\\"\"
|
||||||
}
|
}
|
||||||
|
|
||||||
linux-g++ {
|
linux-g++ {
|
||||||
|
@ -291,7 +291,7 @@ mac {
|
||||||
#LIBS += -lsqlite3
|
#LIBS += -lsqlite3
|
||||||
|
|
||||||
DEFINES *= PLUGIN_DIR=\"\\\"$${PLUGIN_DIR}\\\"\"
|
DEFINES *= PLUGIN_DIR=\"\\\"$${PLUGIN_DIR}\\\"\"
|
||||||
DEFINES *= DATA_DIR=\"\\\"$${DATA_DIR}\\\"\"
|
DEFINES *= RS_DATA_DIR=\"\\\"$${RS_DATA_DIR}\\\"\"
|
||||||
}
|
}
|
||||||
|
|
||||||
################################# FreeBSD ##########################################
|
################################# FreeBSD ##########################################
|
||||||
|
@ -365,6 +365,7 @@ HEADERS += chat/distantchat.h \
|
||||||
HEADERS += pqi/authssl.h \
|
HEADERS += pqi/authssl.h \
|
||||||
pqi/authgpg.h \
|
pqi/authgpg.h \
|
||||||
pgp/pgphandler.h \
|
pgp/pgphandler.h \
|
||||||
|
pgp/openpgpsdkhandler.h \
|
||||||
pgp/pgpkeyutil.h \
|
pgp/pgpkeyutil.h \
|
||||||
pqi/pqifdbin.h \
|
pqi/pqifdbin.h \
|
||||||
pqi/rstcpsocket.h \
|
pqi/rstcpsocket.h \
|
||||||
|
@ -511,6 +512,7 @@ HEADERS += util/folderiterator.h \
|
||||||
util/cxx11retrocompat.h \
|
util/cxx11retrocompat.h \
|
||||||
util/cxx14retrocompat.h \
|
util/cxx14retrocompat.h \
|
||||||
util/cxx17retrocompat.h \
|
util/cxx17retrocompat.h \
|
||||||
|
util/cxx23retrocompat.h \
|
||||||
util/rsurl.h
|
util/rsurl.h
|
||||||
|
|
||||||
SOURCES += ft/ftchunkmap.cc \
|
SOURCES += ft/ftchunkmap.cc \
|
||||||
|
@ -538,6 +540,7 @@ SOURCES += chat/distantchat.cc \
|
||||||
SOURCES += pqi/authgpg.cc \
|
SOURCES += pqi/authgpg.cc \
|
||||||
pqi/authssl.cc \
|
pqi/authssl.cc \
|
||||||
pgp/pgphandler.cc \
|
pgp/pgphandler.cc \
|
||||||
|
pgp/openpgpsdkhandler.cc \
|
||||||
pgp/pgpkeyutil.cc \
|
pgp/pgpkeyutil.cc \
|
||||||
pgp/rscertificate.cc \
|
pgp/rscertificate.cc \
|
||||||
pgp/pgpauxutils.cc \
|
pgp/pgpauxutils.cc \
|
||||||
|
@ -1132,6 +1135,8 @@ test_bitdht {
|
||||||
################################# Android #####################################
|
################################# Android #####################################
|
||||||
|
|
||||||
android-* {
|
android-* {
|
||||||
|
lessThan(ANDROID_API_VERSION, 24) {
|
||||||
|
|
||||||
## TODO: This probably disable largefile support and maybe is not necessary with
|
## TODO: This probably disable largefile support and maybe is not necessary with
|
||||||
## __ANDROID_API__ >= 24 hence should be made conditional or moved to a
|
## __ANDROID_API__ >= 24 hence should be made conditional or moved to a
|
||||||
## compatibility header
|
## compatibility header
|
||||||
|
@ -1139,12 +1144,26 @@ android-* {
|
||||||
DEFINES *= "fseeko64=fseeko"
|
DEFINES *= "fseeko64=fseeko"
|
||||||
DEFINES *= "ftello64=ftello"
|
DEFINES *= "ftello64=ftello"
|
||||||
|
|
||||||
|
## @See: rs_android/README-ifaddrs-android.adoc
|
||||||
|
HEADERS += \
|
||||||
|
rs_android/ifaddrs-android.h \
|
||||||
|
rs_android/LocalArray.h \
|
||||||
|
rs_android/ScopedFd.h
|
||||||
|
}
|
||||||
|
|
||||||
## Static library are very susceptible to order in command line
|
## Static library are very susceptible to order in command line
|
||||||
sLibs = bz2 $$RS_UPNP_LIB $$RS_SQL_LIB ssl crypto
|
sLibs = bz2 $$RS_UPNP_LIB $$RS_SQL_LIB ssl crypto
|
||||||
|
|
||||||
LIBS += $$linkStaticLibs(sLibs)
|
LIBS += $$linkStaticLibs(sLibs)
|
||||||
PRE_TARGETDEPS += $$pretargetStaticLibs(sLibs)
|
PRE_TARGETDEPS += $$pretargetStaticLibs(sLibs)
|
||||||
|
|
||||||
HEADERS += util/androiddebug.h
|
HEADERS += \
|
||||||
|
rs_android/androidcoutcerrcatcher.hpp \
|
||||||
|
rs_android/retroshareserviceandroid.hpp \
|
||||||
|
rs_android/rsjni.hpp
|
||||||
|
|
||||||
|
SOURCES += rs_android/rsjni.cpp \
|
||||||
|
rs_android/retroshareserviceandroid.cpp \
|
||||||
|
rs_android/errorconditionwrap.cpp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1810
libretroshare/src/pgp/openpgpsdkhandler.cc
Normal file
1810
libretroshare/src/pgp/openpgpsdkhandler.cc
Normal file
File diff suppressed because it is too large
Load diff
116
libretroshare/src/pgp/openpgpsdkhandler.h
Normal file
116
libretroshare/src/pgp/openpgpsdkhandler.h
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* libretroshare/src/pgp: pgphandler.h *
|
||||||
|
* *
|
||||||
|
* libretroshare: retroshare core library *
|
||||||
|
* *
|
||||||
|
* Copyright 2018 Cyril Soler <csoler@users.sourceforge.net> *
|
||||||
|
* *
|
||||||
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
* published by the Free Software Foundation, either version 3 of the *
|
||||||
|
* License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License *
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
*******************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string>
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include "util/rsthreads.h"
|
||||||
|
#include "pgp/pgphandler.h"
|
||||||
|
#include "retroshare/rstypes.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
// we should make sure later on to get rid of these structures in the .h
|
||||||
|
#include "openpgpsdk/keyring.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This class offer an abstract pgp handler to be used in RetroShare.
|
||||||
|
class OpenPGPSDKHandler: public PGPHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OpenPGPSDKHandler( 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 ~OpenPGPSDKHandler() ;
|
||||||
|
|
||||||
|
//================================================================================================//
|
||||||
|
// Implemented API from PGPHandler //
|
||||||
|
//================================================================================================//
|
||||||
|
|
||||||
|
//virtual std::string makeRadixEncodedPGPKey(uint32_t key_index,bool include_signatures) override;
|
||||||
|
virtual bool removeKeysFromPGPKeyring(const std::set<RsPgpId>& key_ids,std::string& backup_file,uint32_t& error_code) override;
|
||||||
|
virtual bool availableGPGCertificatesWithPrivateKeys(std::list<RsPgpId>& ids) override;
|
||||||
|
virtual bool GeneratePGPCertificate(const std::string& name, const std::string& email, const std::string& passphrase, RsPgpId& pgpId, const int keynumbits, std::string& errString) override;
|
||||||
|
|
||||||
|
virtual std::string SaveCertificateToString(const RsPgpId& id,bool include_signatures) const override;
|
||||||
|
virtual bool exportPublicKey( const RsPgpId& id, unsigned char*& mem_block, size_t& mem_size, bool armoured, bool include_signatures ) const override;
|
||||||
|
|
||||||
|
virtual bool exportGPGKeyPair(const std::string& filename,const RsPgpId& exported_key_id) const override;
|
||||||
|
virtual bool exportGPGKeyPairToString( std::string& data, const RsPgpId& exportedKeyId, bool includeSignatures, std::string& errorMsg ) const override;
|
||||||
|
virtual bool getGPGDetailsFromBinaryBlock(const unsigned char *mem_block,size_t mem_size,RsPgpId& key_id, std::string& name, std::list<RsPgpId>& signers) const override;
|
||||||
|
virtual bool importGPGKeyPair(const std::string& filename,RsPgpId& imported_key_id,std::string& import_error) override;
|
||||||
|
virtual bool importGPGKeyPairFromString(const std::string &data, RsPgpId &imported_key_id, std::string &import_error) override;
|
||||||
|
virtual bool LoadCertificateFromBinaryData(const unsigned char *data,uint32_t data_len,RsPgpId& id,std::string& error_string) override;
|
||||||
|
virtual bool LoadCertificateFromString(const std::string& pgp_cert,RsPgpId& id,std::string& error_string) override;
|
||||||
|
virtual bool encryptTextToFile(const RsPgpId& key_id,const std::string& text,const std::string& outfile) override;
|
||||||
|
virtual bool encryptDataBin(const RsPgpId& key_id,const void *data, const uint32_t len, unsigned char *encrypted_data, unsigned int *encrypted_data_len) override;
|
||||||
|
virtual bool decryptDataBin(const RsPgpId& /*key_id*/,const void *encrypted_data, const uint32_t encrypted_len, unsigned char *data, unsigned int *data_len) override;
|
||||||
|
virtual bool decryptTextFromFile(const RsPgpId&,std::string& text,const std::string& inputfile) override;
|
||||||
|
virtual bool SignDataBin(const RsPgpId& id,const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen,bool use_raw_signature, std::string reason /* = "" */) override;
|
||||||
|
virtual bool privateSignCertificate(const RsPgpId& ownId,const RsPgpId& id_of_key_to_sign) override;
|
||||||
|
virtual bool VerifySignBin(const void *literal_data, uint32_t literal_data_length, unsigned char *sign, unsigned int sign_len, const PGPFingerprintType& key_fingerprint) override;
|
||||||
|
virtual bool getKeyFingerprint(const RsPgpId& id, RsPgpFingerprint& fp) const override;
|
||||||
|
virtual bool haveSecretKey(const RsPgpId& id) const override;
|
||||||
|
virtual bool syncDatabase() override;
|
||||||
|
private:
|
||||||
|
bool locked_syncPublicKeyring() ;
|
||||||
|
|
||||||
|
void initCertificateInfo(PGPCertificateInfo& cert,const ops_keydata_t *keydata,uint32_t i) ;
|
||||||
|
bool LoadCertificate(const unsigned char *data,uint32_t data_len,bool armoured,RsPgpId& id,std::string& error_string) ;
|
||||||
|
|
||||||
|
// 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_mergeKeyringFromDisk(ops_keyring_t *keyring, std::map<RsPgpId,PGPCertificateInfo>& kmap, const std::string& keyring_file) ;
|
||||||
|
bool locked_addOrMergeKey(ops_keyring_t *keyring,std::map<RsPgpId,PGPCertificateInfo>& kmap,const ops_keydata_t *keydata) ;
|
||||||
|
|
||||||
|
// Members.
|
||||||
|
//
|
||||||
|
ops_keyring_t *_pubring ;
|
||||||
|
ops_keyring_t *_secring ;
|
||||||
|
|
||||||
|
void printOPSKeys() const;
|
||||||
|
|
||||||
|
// 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 bool mergeKeySignatures(ops_keydata_t *dst,const ops_keydata_t *src) ; // returns true if signature lists are different
|
||||||
|
};
|
|
@ -34,17 +34,17 @@ PgpAuxUtilsImpl::PgpAuxUtilsImpl()
|
||||||
|
|
||||||
const RsPgpId& PgpAuxUtilsImpl::getPGPOwnId()
|
const RsPgpId& PgpAuxUtilsImpl::getPGPOwnId()
|
||||||
{
|
{
|
||||||
return AuthGPG::getAuthGPG()->getGPGOwnId();
|
return AuthPGP::getPgpOwnId();
|
||||||
}
|
}
|
||||||
|
|
||||||
RsPgpId PgpAuxUtilsImpl::getPGPId(const RsPeerId& sslid)
|
RsPgpId PgpAuxUtilsImpl::getPgpId(const RsPeerId& sslid)
|
||||||
{
|
{
|
||||||
return rsPeers->getGPGId(sslid);
|
return rsPeers->getGPGId(sslid);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PgpAuxUtilsImpl::getKeyFingerprint(const RsPgpId& id,PGPFingerprintType& fp) const
|
bool PgpAuxUtilsImpl::getKeyFingerprint(const RsPgpId& id,PGPFingerprintType& fp) const
|
||||||
{
|
{
|
||||||
return AuthGPG::getAuthGPG()->getKeyFingerprint(id, fp);
|
return AuthPGP::getKeyFingerprint(id, fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PgpAuxUtilsImpl::VerifySignBin(const void *data,
|
bool PgpAuxUtilsImpl::VerifySignBin(const void *data,
|
||||||
|
@ -54,17 +54,17 @@ bool PgpAuxUtilsImpl::VerifySignBin(const void *data,
|
||||||
const PGPFingerprintType& withfingerprint)
|
const PGPFingerprintType& withfingerprint)
|
||||||
|
|
||||||
{
|
{
|
||||||
return AuthGPG::getAuthGPG()->VerifySignBin(data, len, sign, signlen, withfingerprint);
|
return AuthPGP::VerifySignBin(data, len, sign, signlen, withfingerprint);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PgpAuxUtilsImpl::getGPGAllList(std::list<RsPgpId> &ids)
|
bool PgpAuxUtilsImpl::getPgpAllList(std::list<RsPgpId> &ids)
|
||||||
{
|
{
|
||||||
return AuthGPG::getAuthGPG()->getGPGAllList(ids);
|
return AuthPGP::getPgpAllList(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PgpAuxUtilsImpl::parseSignature(unsigned char *sign, unsigned int signlen, RsPgpId& issuer) const
|
bool PgpAuxUtilsImpl::parseSignature(unsigned char *sign, unsigned int signlen, RsPgpId& issuer) const
|
||||||
{
|
{
|
||||||
return AuthGPG::getAuthGPG()->parseSignature(sign,signlen,issuer);
|
return AuthPGP::parseSignature(sign,signlen,issuer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,8 +35,8 @@ class PgpAuxUtils
|
||||||
virtual ~PgpAuxUtils(){}
|
virtual ~PgpAuxUtils(){}
|
||||||
|
|
||||||
virtual const RsPgpId &getPGPOwnId() = 0;
|
virtual const RsPgpId &getPGPOwnId() = 0;
|
||||||
virtual RsPgpId getPGPId(const RsPeerId& sslid) = 0;
|
virtual RsPgpId getPgpId(const RsPeerId& sslid) = 0;
|
||||||
virtual bool getGPGAllList(std::list<RsPgpId> &ids) = 0;
|
virtual bool getPgpAllList(std::list<RsPgpId> &ids) = 0;
|
||||||
virtual bool getKeyFingerprint(const RsPgpId& id,PGPFingerprintType& fp) const = 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 parseSignature(unsigned char *sign, unsigned int signlen, RsPgpId& issuer) const =0;
|
||||||
|
@ -49,12 +49,12 @@ public:
|
||||||
PgpAuxUtilsImpl();
|
PgpAuxUtilsImpl();
|
||||||
|
|
||||||
virtual const RsPgpId &getPGPOwnId();
|
virtual const RsPgpId &getPGPOwnId();
|
||||||
virtual RsPgpId getPGPId(const RsPeerId& sslid);
|
virtual RsPgpId getPgpId(const RsPeerId& sslid);
|
||||||
|
|
||||||
virtual bool parseSignature(unsigned char *sign, unsigned int signlen, RsPgpId& issuer) const ;
|
virtual bool parseSignature(unsigned char *sign, unsigned int signlen, RsPgpId& issuer) const ;
|
||||||
virtual bool getKeyFingerprint(const RsPgpId& id,PGPFingerprintType& fp) 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 VerifySignBin(const void *data, uint32_t len, unsigned char *sign, unsigned int signlen, const PGPFingerprintType& withfingerprint);
|
||||||
virtual bool getGPGAllList(std::list<RsPgpId> &ids);
|
virtual bool getPgpAllList(std::list<RsPgpId> &ids);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -29,12 +29,6 @@
|
||||||
#include <util/rsthreads.h>
|
#include <util/rsthreads.h>
|
||||||
#include <retroshare/rstypes.h>
|
#include <retroshare/rstypes.h>
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <openpgpsdk/types.h>
|
|
||||||
#include <openpgpsdk/keyring.h>
|
|
||||||
#include <openpgpsdk/keyring_local.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef std::string (*PassphraseCallback)(void *data, const char *uid_title, const char *uid_hint, const char *passphrase_info, int prev_was_bad,bool *cancelled) ;
|
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
|
class PGPCertificateInfo
|
||||||
|
@ -56,9 +50,11 @@ class PGPCertificateInfo
|
||||||
mutable rstime_t _time_stamp ; // last time the key was used (received, used for signature verification, etc)
|
mutable rstime_t _time_stamp ; // last time the key was used (received, used for signature verification, etc)
|
||||||
|
|
||||||
PGPFingerprintType _fpr; /* fingerprint */
|
PGPFingerprintType _fpr; /* fingerprint */
|
||||||
// RsPgpId _key_id ;
|
|
||||||
|
|
||||||
uint32_t _key_index ; // index to array of keys in the public keyring
|
// Index to array of keys in the public keyring. Dependign on the specific implementation
|
||||||
|
// of how the keyring is stored, this may be used differently.
|
||||||
|
|
||||||
|
uint32_t _key_index ;
|
||||||
|
|
||||||
static const uint32_t PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION = 0x0001 ;
|
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_OWN_SIGNATURE = 0x0002 ;
|
||||||
|
@ -87,46 +83,80 @@ public:
|
||||||
|
|
||||||
virtual ~PGPHandler() ;
|
virtual ~PGPHandler() ;
|
||||||
|
|
||||||
|
//=======================================================================================//
|
||||||
|
// Methods that needs to be derived depending on how PGP is implemented //
|
||||||
|
//=======================================================================================//
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
virtual bool removeKeysFromPGPKeyring(const std::set<RsPgpId>& key_ids,std::string& backup_file,uint32_t& error_code) =0;
|
||||||
|
//virtual std::string makeRadixEncodedPGPKey(uint32_t key_index,bool include_signatures) =0;
|
||||||
|
|
||||||
|
virtual bool availableGPGCertificatesWithPrivateKeys(std::list<RsPgpId>& ids)=0;
|
||||||
|
virtual bool GeneratePGPCertificate(const std::string& name, const std::string& email, const std::string& passwd, RsPgpId& pgpId, const int keynumbits, std::string& errString) =0;
|
||||||
|
|
||||||
|
virtual std::string SaveCertificateToString(const RsPgpId& id,bool include_signatures) const=0;
|
||||||
|
|
||||||
|
/** The caller is in charge of freeing `mem` once finished */
|
||||||
|
virtual bool exportPublicKey( const RsPgpId& id, unsigned char*& mem_block, size_t& mem_size, bool armoured, bool include_signatures ) const =0;
|
||||||
|
|
||||||
|
virtual bool exportGPGKeyPair(const std::string& filename,const RsPgpId& exported_key_id) const=0;
|
||||||
|
virtual bool exportGPGKeyPairToString( std::string& data, const RsPgpId& exportedKeyId, bool includeSignatures, std::string& errorMsg ) const =0;
|
||||||
|
|
||||||
|
// Gets info about the key. Who are the signers, what's the owner's name, etc.
|
||||||
|
//
|
||||||
|
virtual bool getGPGDetailsFromBinaryBlock(const unsigned char *mem,size_t mem_size,RsPgpId& key_id, std::string& name, std::list<RsPgpId>& signers) const =0;
|
||||||
|
|
||||||
|
virtual bool importGPGKeyPair(const std::string& filename,RsPgpId& imported_id,std::string& import_error) =0;
|
||||||
/**
|
/**
|
||||||
* @param ids list of gpg certificate ids (note, not the actual certificates)
|
* @param ids list of gpg certificate ids (note, not the actual certificates)
|
||||||
*/
|
*/
|
||||||
bool getGPGFilteredList(std::list<RsPgpId>& 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) ;
|
virtual bool importGPGKeyPairFromString(const std::string& data,RsPgpId& imported_id,std::string& import_error) =0;
|
||||||
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<RsPgpId>& ids);
|
virtual bool LoadCertificateFromString(const std::string& pem, RsPgpId& gpg_id, std::string& error_string)=0;
|
||||||
bool GeneratePGPCertificate(const std::string& name, const std::string& email, const std::string& passwd, RsPgpId& pgpId, const int keynumbits, std::string& errString) ;
|
virtual bool LoadCertificateFromBinaryData(const unsigned char *bin_data,uint32_t bin_data_len, RsPgpId& gpg_id, std::string& error_string)=0;
|
||||||
|
|
||||||
bool LoadCertificateFromString(const std::string& pem, RsPgpId& gpg_id, std::string& error_string);
|
virtual bool encryptTextToFile(const RsPgpId& key_id,const std::string& text,const std::string& outfile) =0;
|
||||||
bool LoadCertificateFromBinaryData(const unsigned char *bin_data,uint32_t bin_data_len, RsPgpId& gpg_id, std::string& error_string);
|
virtual bool decryptTextFromFile(const RsPgpId& key_id,std::string& text,const std::string& encrypted_inputfile) =0;
|
||||||
|
|
||||||
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.
|
// 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
|
virtual bool encryptDataBin(const RsPgpId& key_id,const void *data, const uint32_t len , unsigned char *encrypted_data, unsigned int *encrypted_data_len) =0;
|
||||||
, unsigned char *encrypted_data, unsigned int *encrypted_data_len) ;
|
virtual bool decryptDataBin(const RsPgpId& key_id,const void *encrypted_data, const uint32_t encrypted_len , unsigned char *data, unsigned int *data_len) =0;
|
||||||
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) ;
|
virtual 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 = "") =0;
|
||||||
bool decryptTextFromFile(const RsPgpId& key_id,std::string& text,const std::string& encrypted_inputfile) ;
|
virtual bool privateSignCertificate(const RsPgpId& own_id,const RsPgpId& id_of_key_to_sign) =0;
|
||||||
|
virtual bool VerifySignBin(const void *data, uint32_t data_len, unsigned char *sign, unsigned int sign_len, const PGPFingerprintType& withfingerprint) =0;
|
||||||
|
/**
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
virtual bool getKeyFingerprint(const RsPgpId& id, RsPgpFingerprint& fp) const=0;
|
||||||
|
|
||||||
|
virtual bool haveSecretKey(const RsPgpId& id) const =0;
|
||||||
|
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
virtual bool syncDatabase() =0;
|
||||||
|
|
||||||
|
|
||||||
|
//=======================================================================================//
|
||||||
|
// Common methods to PGPHandler //
|
||||||
|
//=======================================================================================//
|
||||||
|
|
||||||
|
bool getGPGFilteredList(std::list<RsPgpId>& list,bool (*filter)(const PGPCertificateInfo&) = NULL) const ;
|
||||||
|
|
||||||
|
bool parseSignature(unsigned char *sign, unsigned int signlen,RsPgpId& issuer_id) ;
|
||||||
|
|
||||||
void setAcceptConnexion(const RsPgpId&,bool) ;
|
void setAcceptConnexion(const RsPgpId&,bool) ;
|
||||||
|
|
||||||
|
@ -135,11 +165,6 @@ public:
|
||||||
|
|
||||||
void locked_updateOwnSignatureFlag(PGPCertificateInfo&, const RsPgpId&, PGPCertificateInfo&, const RsPgpId&) ;
|
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<RsPgpId>& key_ids,std::string& backup_file,uint32_t& error_code) ;
|
|
||||||
|
|
||||||
//bool isKeySupported(const RsPgpId& id) const ;
|
//bool isKeySupported(const RsPgpId& id) const ;
|
||||||
|
|
||||||
bool privateTrustCertificate(const RsPgpId& id,int valid_level) ;
|
bool privateTrustCertificate(const RsPgpId& id,int valid_level) ;
|
||||||
|
@ -174,66 +199,18 @@ public:
|
||||||
*/
|
*/
|
||||||
static RsPgpId pgpIdFromFingerprint(const RsPgpFingerprint& f);
|
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<RsPgpId>& signers) const ;
|
|
||||||
|
|
||||||
// Debug stuff.
|
// Debug stuff.
|
||||||
virtual bool printKeys() const ;
|
virtual bool printKeys() const ;
|
||||||
|
|
||||||
// Syncs the keyrings and trust database between memory and disk. The algorithm is:
|
protected:
|
||||||
// 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() ;
|
void locked_readPrivateTrustDatabase() ;
|
||||||
bool locked_writePrivateTrustDatabase() ;
|
bool locked_writePrivateTrustDatabase() ;
|
||||||
|
|
||||||
bool locked_syncPublicKeyring() ;
|
|
||||||
bool locked_syncTrustDatabase() ;
|
bool locked_syncTrustDatabase() ;
|
||||||
|
|
||||||
void locked_mergeKeyringFromDisk(ops_keyring_t *keyring, std::map<RsPgpId,PGPCertificateInfo>& kmap, const std::string& keyring_file) ;
|
|
||||||
bool locked_addOrMergeKey(ops_keyring_t *keyring,std::map<RsPgpId,PGPCertificateInfo>& kmap,const ops_keydata_t *keydata) ;
|
|
||||||
|
|
||||||
// Members.
|
// Members.
|
||||||
//
|
//
|
||||||
mutable RsMutex pgphandlerMtx ;
|
mutable RsMutex pgphandlerMtx ;
|
||||||
|
|
||||||
ops_keyring_t *_pubring ;
|
|
||||||
ops_keyring_t *_secring ;
|
|
||||||
|
|
||||||
std::map<RsPgpId,PGPCertificateInfo> _public_keyring_map ; // used for fast access to keys. Gives the index in the keyring.
|
std::map<RsPgpId,PGPCertificateInfo> _public_keyring_map ; // used for fast access to keys. Gives the index in the keyring.
|
||||||
std::map<RsPgpId,PGPCertificateInfo> _secret_keyring_map ;
|
std::map<RsPgpId,PGPCertificateInfo> _secret_keyring_map ;
|
||||||
|
|
||||||
|
@ -249,11 +226,5 @@ public:
|
||||||
rstime_t _secring_last_update_time ;
|
rstime_t _secring_last_update_time ;
|
||||||
rstime_t _trustdb_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 PassphraseCallback _passphrase_callback ;
|
||||||
static bool mergeKeySignatures(ops_keydata_t *dst,const ops_keydata_t *src) ; // returns true if signature lists are different
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -552,11 +552,10 @@ unsigned short RsCertificate::loc_port_us() const
|
||||||
return (int)ipv4_internal_ip_and_port[4]*256 + (int)ipv4_internal_ip_and_port[5] ;
|
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 )
|
bool RsCertificate::cleanCertificate( const std::string& input, std::string& output, Format& format, uint32_t& error_code, bool check_content, RsPeerDetails& details)
|
||||||
{
|
{
|
||||||
if(cleanRadix64(input,output,error_code))
|
if(cleanRadix64(input,output,error_code))
|
||||||
{
|
{
|
||||||
RsPeerDetails details;
|
|
||||||
|
|
||||||
if(rsPeers->parseShortInvite(output,details,error_code))
|
if(rsPeers->parseShortInvite(output,details,error_code))
|
||||||
{
|
{
|
||||||
|
@ -564,14 +563,13 @@ bool RsCertificate::cleanCertificate( const std::string& input, std::string& out
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Clear details. As parseShortInvite may make it dirty.
|
||||||
|
details = RsPeerDetails();
|
||||||
format = RS_CERTIFICATE_RADIX;
|
format = RS_CERTIFICATE_RADIX;
|
||||||
|
|
||||||
if(!check_content) return true;
|
if(!check_content) return true;
|
||||||
|
|
||||||
uint32_t errCode;
|
return rsPeers->loadDetailsFromStringCert(input,details,error_code);
|
||||||
auto crt = RsCertificate::fromString(input, errCode);
|
|
||||||
error_code = static_cast<int>(errCode);
|
|
||||||
return crt != nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -84,7 +84,7 @@ public:
|
||||||
|
|
||||||
static bool cleanCertificate(
|
static bool cleanCertificate(
|
||||||
const std::string& input, std::string& output,
|
const std::string& input, std::string& output,
|
||||||
RsCertificate::Format& format, uint32_t& error_code, bool check_content);
|
RsCertificate::Format& format, uint32_t& error_code, bool check_content, RsPeerDetails& details);
|
||||||
|
|
||||||
const std::set<RsUrl>& locators() const { return mLocators; }
|
const std::set<RsUrl>& locators() const { return mLocators; }
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
|
|
||||||
//const rstime_t STORE_KEY_TIMEOUT = 1 * 60 * 60; //store key is call around every hour
|
//const rstime_t STORE_KEY_TIMEOUT = 1 * 60 * 60; //store key is call around every hour
|
||||||
|
|
||||||
AuthGPG *AuthGPG::_instance = NULL ;
|
AuthPGP *AuthPGP::_instance = NULL ;
|
||||||
|
|
||||||
void cleanupZombies(int numkill); // function to cleanup zombies under OSX.
|
void cleanupZombies(int numkill); // function to cleanup zombies under OSX.
|
||||||
|
|
||||||
|
@ -54,34 +54,46 @@ void cleanupZombies(int numkill); // function to cleanup zombies under OSX.
|
||||||
|
|
||||||
/* Function to sign X509_REQ via GPGme. */
|
/* Function to sign X509_REQ via GPGme. */
|
||||||
|
|
||||||
bool AuthGPG::decryptTextFromFile(std::string& text,const std::string& inputfile)
|
int AuthPGP::availablePgpCertificatesWithPrivateKeys(std::list<RsPgpId>& pgpIds)
|
||||||
{
|
{
|
||||||
return PGPHandler::decryptTextFromFile(mOwnGpgId,text,inputfile) ;
|
return instance()->mPgpHandler->availableGPGCertificatesWithPrivateKeys(pgpIds);
|
||||||
|
}
|
||||||
|
bool AuthPGP::getPgpDetailsFromBinaryBlock(const unsigned char *mem,size_t mem_size,RsPgpId& key_id, std::string& name, std::list<RsPgpId>& signers)
|
||||||
|
{
|
||||||
|
return instance()->mPgpHandler->getGPGDetailsFromBinaryBlock(mem,mem_size,key_id,name,signers);
|
||||||
|
}
|
||||||
|
void AuthPGP::registerToConfigMgr(const std::string& fname,p3ConfigMgr *CfgMgr)
|
||||||
|
{
|
||||||
|
CfgMgr->addConfiguration(fname, instance());
|
||||||
|
}
|
||||||
|
bool AuthPGP::decryptTextFromFile(std::string& text,const std::string& inputfile)
|
||||||
|
{
|
||||||
|
return instance()->mPgpHandler->decryptTextFromFile(instance()->mOwnGpgId,text,inputfile) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthGPG::removeKeysFromPGPKeyring(const std::set<RsPgpId>& pgp_ids,std::string& backup_file,uint32_t& error_code)
|
bool AuthPGP::removeKeysFromPGPKeyring(const std::set<RsPgpId>& pgp_ids,std::string& backup_file,uint32_t& error_code)
|
||||||
{
|
{
|
||||||
// std::list<RsPgpId> pids ;
|
// std::list<RsPgpId> pids ;
|
||||||
//
|
//
|
||||||
// for(std::list<RsPgpId>::const_iterator it(pgp_ids.begin());it!=pgp_ids.end();++it)
|
// for(std::list<RsPgpId>::const_iterator it(pgp_ids.begin());it!=pgp_ids.end();++it)
|
||||||
// pids.push_back(RsPgpId(*it)) ;
|
// pids.push_back(RsPgpId(*it)) ;
|
||||||
|
|
||||||
return PGPHandler::removeKeysFromPGPKeyring(pgp_ids,backup_file,error_code) ;
|
return instance()->mPgpHandler->removeKeysFromPGPKeyring(pgp_ids,backup_file,error_code) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// bool AuthGPG::decryptTextFromString(std::string& encrypted_text,std::string& output)
|
// bool AuthGPG::decryptTextFromString(std::string& encrypted_text,std::string& output)
|
||||||
// {
|
// {
|
||||||
// return PGPHandler::decryptTextFromString(mOwnGpgId,encrypted_text,output) ;
|
// return instance()->mPgpHandler->decryptTextFromString(mOwnGpgId,encrypted_text,output) ;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
bool AuthGPG::encryptTextToFile(const std::string& text,const std::string& outfile)
|
bool AuthPGP::encryptTextToFile(const std::string& text,const std::string& outfile)
|
||||||
{
|
{
|
||||||
return PGPHandler::encryptTextToFile(mOwnGpgId,text,outfile) ;
|
return instance()->mPgpHandler->encryptTextToFile(instance()->mOwnGpgId,text,outfile) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// bool AuthGPG::encryptTextToString(const std::string& pgp_id,const std::string& text,std::string& outstr)
|
// bool AuthGPG::encryptTextToString(const std::string& pgp_id,const std::string& text,std::string& outstr)
|
||||||
// {
|
// {
|
||||||
// return PGPHandler::encryptTextToString(RsPgpId(pgp_id),text,outstr) ;
|
// return instance()->mPgpHandler->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)
|
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)
|
||||||
|
@ -95,7 +107,7 @@ std::string pgp_pwd_callback(void * /*hook*/, const char *uid_title, const char
|
||||||
return password ;
|
return password ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AuthGPG::init(
|
void AuthPGP::init(
|
||||||
const std::string& path_to_public_keyring,
|
const std::string& path_to_public_keyring,
|
||||||
const std::string& path_to_secret_keyring,
|
const std::string& path_to_secret_keyring,
|
||||||
const std::string& path_to_trustdb,
|
const std::string& path_to_trustdb,
|
||||||
|
@ -107,14 +119,14 @@ void AuthGPG::init(
|
||||||
std::cerr << "AuthGPG::init() called twice!" << std::endl ;
|
std::cerr << "AuthGPG::init() called twice!" << std::endl ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if(cb) PGPHandler::setPassphraseCallback(cb);else
|
// if(cb) instance()->mPgpHandler->setPassphraseCallback(cb);else
|
||||||
PGPHandler::setPassphraseCallback(pgp_pwd_callback);
|
instance()->mPgpHandler->setPassphraseCallback(pgp_pwd_callback);
|
||||||
_instance = new AuthGPG( path_to_public_keyring,
|
_instance = new AuthPGP( path_to_public_keyring,
|
||||||
path_to_secret_keyring,
|
path_to_secret_keyring,
|
||||||
path_to_trustdb, pgp_lock_file );
|
path_to_trustdb, pgp_lock_file );
|
||||||
}
|
}
|
||||||
|
|
||||||
void AuthGPG::exit()
|
void AuthPGP::exit()
|
||||||
{
|
{
|
||||||
if(_instance)
|
if(_instance)
|
||||||
{
|
{
|
||||||
|
@ -124,9 +136,8 @@ void AuthGPG::exit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
AuthPGP::AuthPGP(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(),
|
:p3Config(),
|
||||||
PGPHandler(path_to_public_keyring,path_to_secret_keyring,path_to_trustdb,pgp_lock_file),
|
|
||||||
gpgMtxService("AuthGPG-service"),
|
gpgMtxService("AuthGPG-service"),
|
||||||
gpgMtxEngine("AuthGPG-engine"),
|
gpgMtxEngine("AuthGPG-engine"),
|
||||||
gpgMtxData("AuthGPG-data"),
|
gpgMtxData("AuthGPG-data"),
|
||||||
|
@ -135,6 +146,8 @@ AuthGPG::AuthGPG(const std::string& path_to_public_keyring,const std::string& pa
|
||||||
_force_sync_database(false),
|
_force_sync_database(false),
|
||||||
mCount(0)
|
mCount(0)
|
||||||
{
|
{
|
||||||
|
mPgpHandler = new OpenPGPSDKHandler(path_to_public_keyring,path_to_secret_keyring,path_to_trustdb,pgp_lock_file);
|
||||||
|
|
||||||
start("AuthGPG");
|
start("AuthGPG");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +162,7 @@ AuthGPG::AuthGPG(const std::string& path_to_public_keyring,const std::string& pa
|
||||||
//{
|
//{
|
||||||
// std::list<RsPgpId> pids ;
|
// std::list<RsPgpId> pids ;
|
||||||
//
|
//
|
||||||
// PGPHandler::availableGPGCertificatesWithPrivateKeys(pids) ;
|
// mPgpHandler->availableGPGCertificatesWithPrivateKeys(pids) ;
|
||||||
//
|
//
|
||||||
// for(std::list<RsPgpId>::const_iterator it(pids.begin());it!=pids.end();++it)
|
// for(std::list<RsPgpId>::const_iterator it(pids.begin());it!=pids.end();++it)
|
||||||
// ids.push_back( (*it).toStdString() ) ;
|
// ids.push_back( (*it).toStdString() ) ;
|
||||||
|
@ -165,17 +178,17 @@ AuthGPG::AuthGPG(const std::string& path_to_public_keyring,const std::string& pa
|
||||||
* This function must be called successfully (return == 1)
|
* This function must be called successfully (return == 1)
|
||||||
* before anything else can be done. (except above fn).
|
* before anything else can be done. (except above fn).
|
||||||
*/
|
*/
|
||||||
int AuthGPG::GPGInit(const RsPgpId &ownId)
|
int AuthPGP::PgpInit(const RsPgpId &ownId)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_AUTHGPG
|
#ifdef DEBUG_AUTHGPG
|
||||||
std::cerr << "AuthGPG::GPGInit() called with own gpg id : " << ownId.toStdString() << std::endl;
|
std::cerr << "AuthGPG::GPGInit() called with own gpg id : " << ownId.toStdString() << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mOwnGpgId = RsPgpId(ownId);
|
instance()->mOwnGpgId = ownId;
|
||||||
|
|
||||||
//force the validity of the private key. When set to unknown, it caused signature and text encryptions bugs
|
//force the validity of the private key. When set to unknown, it caused signature and text encryptions bugs
|
||||||
privateTrustCertificate(ownId, 5);
|
instance()->privateTrustCertificate(ownId, 5);
|
||||||
updateOwnSignatureFlag(mOwnGpgId) ;
|
instance()->mPgpHandler->updateOwnSignatureFlag(ownId) ;
|
||||||
|
|
||||||
#ifdef DEBUG_AUTHGPG
|
#ifdef DEBUG_AUTHGPG
|
||||||
std::cerr << "AuthGPG::GPGInit finished." << std::endl;
|
std::cerr << "AuthGPG::GPGInit finished." << std::endl;
|
||||||
|
@ -184,11 +197,11 @@ int AuthGPG::GPGInit(const RsPgpId &ownId)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthGPG::~AuthGPG()
|
AuthPGP::~AuthPGP()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void AuthGPG::threadTick()
|
void AuthPGP::threadTick()
|
||||||
{
|
{
|
||||||
rstime::rs_usleep(100 * 1000); //100 msec
|
rstime::rs_usleep(100 * 1000); //100 msec
|
||||||
|
|
||||||
|
@ -204,13 +217,13 @@ void AuthGPG::threadTick()
|
||||||
/// - checks whether the keyring has changed on disk.
|
/// - checks whether the keyring has changed on disk.
|
||||||
/// - merges/updates according to status.
|
/// - merges/updates according to status.
|
||||||
///
|
///
|
||||||
PGPHandler::syncDatabase() ;
|
mPgpHandler->syncDatabase() ;
|
||||||
mCount = 0;
|
mCount = 0;
|
||||||
_force_sync_database = false ;
|
_force_sync_database = false ;
|
||||||
}//if (++count >= 100 || _force_sync_database)
|
}//if (++count >= 100 || _force_sync_database)
|
||||||
}
|
}
|
||||||
|
|
||||||
void AuthGPG::processServices()
|
void AuthPGP::processServices()
|
||||||
{
|
{
|
||||||
AuthGPGOperation *operation = NULL;
|
AuthGPGOperation *operation = NULL;
|
||||||
AuthGPGService *service = NULL;
|
AuthGPGService *service = NULL;
|
||||||
|
@ -251,7 +264,7 @@ void AuthGPG::processServices()
|
||||||
|
|
||||||
|
|
||||||
/* don't bother loading - if we already have the certificate */
|
/* don't bother loading - if we already have the certificate */
|
||||||
if (isGPGId(loadOrSave->m_certGpgId))
|
if (mPgpHandler->isGPGId(loadOrSave->m_certGpgId))
|
||||||
{
|
{
|
||||||
#ifdef GPG_DEBUG
|
#ifdef GPG_DEBUG
|
||||||
std::cerr << "AuthGPGimpl::processServices() Skipping load - already have it" << std::endl;
|
std::cerr << "AuthGPGimpl::processServices() Skipping load - already have it" << std::endl;
|
||||||
|
@ -305,66 +318,66 @@ void AuthGPG::processServices()
|
||||||
delete operation;
|
delete operation;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthGPG::DoOwnSignature(const void *data, unsigned int datalen, void *buf_sigout, unsigned int *outl, std::string reason /* = "" */)
|
bool AuthPGP::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) ;
|
return instance()->mPgpHandler->SignDataBin(mOwnGpgId,data,datalen,(unsigned char *)buf_sigout,outl,false,reason) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* import to GnuPG and other Certificates */
|
/* import to GnuPG and other Certificates */
|
||||||
bool AuthGPG::VerifySignature(const void *data, int datalen, const void *sig, unsigned int siglen, const PGPFingerprintType& withfingerprint)
|
bool AuthPGP::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) ;
|
return instance()->mPgpHandler->VerifySignBin((unsigned char*)data,datalen,(unsigned char*)sig,siglen,withfingerprint) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthGPG::parseSignature(const void *sig, unsigned int siglen, RsPgpId& issuer_id)
|
bool AuthPGP::parseSignature(const void *sig, unsigned int siglen, RsPgpId& issuer_id)
|
||||||
{
|
{
|
||||||
return PGPHandler::parseSignature((unsigned char*)sig,siglen,issuer_id) ;
|
return instance()->mPgpHandler->parseSignature((unsigned char*)sig,siglen,issuer_id) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthGPG::exportProfile(const std::string& fname,const RsPgpId& exported_id)
|
bool AuthPGP::exportProfile(const std::string& fname,const RsPgpId& exported_id)
|
||||||
{
|
{
|
||||||
return PGPHandler::exportGPGKeyPair(fname,exported_id) ;
|
return instance()->mPgpHandler->exportGPGKeyPair(fname,exported_id) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthGPG::exportIdentityToString(
|
bool AuthPGP::exportIdentityToString(
|
||||||
std::string& data, const RsPgpId& pgpId, bool includeSignatures,
|
std::string& data, const RsPgpId& pgpId, bool includeSignatures,
|
||||||
std::string& errorMsg )
|
std::string& errorMsg )
|
||||||
{
|
{
|
||||||
return PGPHandler::exportGPGKeyPairToString(
|
return instance()->mPgpHandler->exportGPGKeyPairToString(
|
||||||
data, pgpId, includeSignatures, errorMsg);
|
data, pgpId, includeSignatures, errorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthGPG::importProfile(const std::string& fname,RsPgpId& imported_id,std::string& import_error)
|
bool AuthPGP::importProfile(const std::string& fname,RsPgpId& imported_id,std::string& import_error)
|
||||||
{
|
{
|
||||||
return PGPHandler::importGPGKeyPair(fname,imported_id,import_error) ;
|
return instance()->mPgpHandler->importGPGKeyPair(fname,imported_id,import_error) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthGPG::importProfileFromString(const std::string &data, RsPgpId &gpg_id, std::string &import_error)
|
bool AuthPGP::importProfileFromString(const std::string &data, RsPgpId &gpg_id, std::string &import_error)
|
||||||
{
|
{
|
||||||
return PGPHandler::importGPGKeyPairFromString(data, gpg_id, import_error);
|
return instance()->mPgpHandler->importGPGKeyPairFromString(data, gpg_id, import_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthGPG::active()
|
bool AuthPGP::active()
|
||||||
{
|
{
|
||||||
RsStackMutex stack(gpgMtxData); /******* LOCKED ******/
|
RsStackMutex stack(instance()->gpgMtxData); /******* LOCKED ******/
|
||||||
|
|
||||||
return gpgKeySelected;
|
return instance()->gpgKeySelected;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthGPG::GeneratePGPCertificate(const std::string& name, const std::string& email, const std::string& passwd, RsPgpId& pgpId, const int keynumbits, std::string& errString)
|
bool AuthPGP::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 ******/
|
RsStackMutex stack(instance()->gpgMtxEngine); /******* LOCKED ******/
|
||||||
|
|
||||||
return PGPHandler::GeneratePGPCertificate(name, email, passwd, pgpId, keynumbits, errString) ;
|
return instance()->mPgpHandler->GeneratePGPCertificate(name, email, passwd, pgpId, keynumbits, errString) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**** These Two are common */
|
/**** These Two are common */
|
||||||
std::string AuthGPG::getGPGName(const RsPgpId& id,bool *success)
|
std::string AuthPGP::getPgpName(const RsPgpId& id,bool *success)
|
||||||
{
|
{
|
||||||
RsStackMutex stack(gpgMtxData); /******* LOCKED ******/
|
RsStackMutex stack(instance()->gpgMtxData); /******* LOCKED ******/
|
||||||
|
|
||||||
const PGPCertificateInfo *info = getCertificateInfo(id) ;
|
const PGPCertificateInfo *info = instance()->mPgpHandler->getCertificateInfo(id) ;
|
||||||
|
|
||||||
if(info != NULL)
|
if(info != NULL)
|
||||||
{
|
{
|
||||||
|
@ -378,11 +391,25 @@ std::string AuthGPG::getGPGName(const RsPgpId& id,bool *success)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**** These Two are common */
|
AuthPGP *AuthPGP::instance()
|
||||||
std::string AuthGPG::getGPGEmail(const RsPgpId& id,bool *success)
|
|
||||||
{
|
{
|
||||||
RsStackMutex stack(gpgMtxData); /******* LOCKED ******/
|
if(!_instance)
|
||||||
const PGPCertificateInfo *info = getCertificateInfo(id) ;
|
{
|
||||||
|
RsFatal() << "AuthGPG::instance() called before AuthGPG::init()! This should not happen." << std::endl;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
bool AuthPGP::isPGPId(const RsPgpId& id)
|
||||||
|
{
|
||||||
|
return instance()->mPgpHandler->isGPGId(id);
|
||||||
|
}
|
||||||
|
/**** These Two are common */
|
||||||
|
std::string AuthPGP::getPgpEmail(const RsPgpId& id,bool *success)
|
||||||
|
{
|
||||||
|
RsStackMutex stack(instance()->gpgMtxData); /******* LOCKED ******/
|
||||||
|
const PGPCertificateInfo *info = instance()->mPgpHandler->getCertificateInfo(id) ;
|
||||||
|
|
||||||
if(info != NULL)
|
if(info != NULL)
|
||||||
{
|
{
|
||||||
|
@ -398,30 +425,30 @@ std::string AuthGPG::getGPGEmail(const RsPgpId& id,bool *success)
|
||||||
|
|
||||||
/**** GPG versions ***/
|
/**** GPG versions ***/
|
||||||
|
|
||||||
const RsPgpId& AuthGPG::getGPGOwnId()
|
const RsPgpId& AuthPGP::getPgpOwnId()
|
||||||
{
|
{
|
||||||
RsStackMutex stack(gpgMtxData); /******* LOCKED ******/
|
RsStackMutex stack(instance()->gpgMtxData); /******* LOCKED ******/
|
||||||
return mOwnGpgId ;
|
return instance()->mOwnGpgId ;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AuthGPG::getGPGOwnName()
|
std::string AuthPGP::getPgpOwnName()
|
||||||
{
|
{
|
||||||
return getGPGName(mOwnGpgId) ;
|
return getPgpName(instance()->mOwnGpgId) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthGPG::getGPGAllList(std::list<RsPgpId> &ids)
|
bool AuthPGP::getPgpAllList(std::list<RsPgpId> &ids)
|
||||||
{
|
{
|
||||||
RsStackMutex stack(gpgMtxData); /******* LOCKED ******/
|
RsStackMutex stack(instance()->gpgMtxData); /******* LOCKED ******/
|
||||||
|
|
||||||
PGPHandler::getGPGFilteredList(ids) ;
|
instance()->mPgpHandler->getGPGFilteredList(ids) ;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const PGPCertificateInfo *AuthGPG::getCertInfoFromStdString(const std::string& pgp_id) const
|
const PGPCertificateInfo *AuthPGP::getCertInfoFromStdString(const std::string& pgp_id) const
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return PGPHandler::getCertificateInfo(RsPgpId(pgp_id)) ;
|
return instance()->mPgpHandler->getCertificateInfo(RsPgpId(pgp_id)) ;
|
||||||
}
|
}
|
||||||
catch(std::exception& e)
|
catch(std::exception& e)
|
||||||
{
|
{
|
||||||
|
@ -429,13 +456,13 @@ const PGPCertificateInfo *AuthGPG::getCertInfoFromStdString(const std::string& p
|
||||||
return NULL ;
|
return NULL ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool AuthGPG::haveSecretKey(const RsPgpId& id) const
|
bool AuthPGP::haveSecretKey(const RsPgpId& id)
|
||||||
{
|
{
|
||||||
return PGPHandler::haveSecretKey(id) ;
|
return instance()->mPgpHandler->haveSecretKey(id) ;
|
||||||
}
|
}
|
||||||
bool AuthGPG::isKeySupported(const RsPgpId& id) const
|
bool AuthPGP::isKeySupported(const RsPgpId& id)
|
||||||
{
|
{
|
||||||
const PGPCertificateInfo *pc = getCertificateInfo(id) ;
|
const PGPCertificateInfo *pc = instance()->mPgpHandler->getCertificateInfo(id) ;
|
||||||
|
|
||||||
if(pc == NULL)
|
if(pc == NULL)
|
||||||
return false ;
|
return false ;
|
||||||
|
@ -443,11 +470,11 @@ bool AuthGPG::isKeySupported(const RsPgpId& id) const
|
||||||
return !(pc->_flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_UNSUPPORTED_ALGORITHM) ;
|
return !(pc->_flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_UNSUPPORTED_ALGORITHM) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthGPG::getGPGDetails(const RsPgpId& pgp_id, RsPeerDetails &d)
|
bool AuthPGP::getPgpDetails(const RsPgpId& pgp_id, RsPeerDetails &d)
|
||||||
{
|
{
|
||||||
RsStackMutex stack(gpgMtxData); /******* LOCKED ******/
|
RsStackMutex stack(instance()->gpgMtxData); /******* LOCKED ******/
|
||||||
|
|
||||||
const PGPCertificateInfo *pc = PGPHandler::getCertificateInfo(pgp_id) ;
|
const PGPCertificateInfo *pc = instance()->mPgpHandler->getCertificateInfo(pgp_id) ;
|
||||||
|
|
||||||
if(pc == NULL)
|
if(pc == NULL)
|
||||||
return false ;
|
return false ;
|
||||||
|
@ -474,28 +501,26 @@ bool AuthGPG::getGPGDetails(const RsPgpId& pgp_id, RsPeerDetails &d)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthGPG::getGPGFilteredList(std::list<RsPgpId>& list,bool (*filter)(const PGPCertificateInfo&))
|
bool AuthPGP::getGPGFilteredList(std::list<RsPgpId>& list,bool (*filter)(const PGPCertificateInfo&))
|
||||||
{
|
{
|
||||||
RsStackMutex stack(gpgMtxData); /******* LOCKED ******/
|
return instance()->mPgpHandler->getGPGFilteredList(list,filter) ;
|
||||||
|
|
||||||
return PGPHandler::getGPGFilteredList(list,filter) ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool filter_Validity(const PGPCertificateInfo& /*info*/) { return true ; } //{ return info._validLvl >= PGPCertificateInfo::GPGME_VALIDITY_MARGINAL ; }
|
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_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 ; }
|
static bool filter_OwnSigned(const PGPCertificateInfo& info) { return info._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE ; }
|
||||||
|
|
||||||
bool AuthGPG::getGPGValidList(std::list<RsPgpId> &ids)
|
bool AuthPGP::getPgpValidList(std::list<RsPgpId> &ids)
|
||||||
{
|
{
|
||||||
return getGPGFilteredList(ids,&filter_Validity);
|
return getGPGFilteredList(ids,&filter_Validity);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthGPG::getGPGAcceptedList(std::list<RsPgpId> &ids)
|
bool AuthPGP::getPgpAcceptedList(std::list<RsPgpId> &ids)
|
||||||
{
|
{
|
||||||
return getGPGFilteredList(ids,&filter_Accepted);
|
return getGPGFilteredList(ids,&filter_Accepted);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthGPG::getGPGSignedList(std::list<RsPgpId> &ids)
|
bool AuthPGP::getPgpSignedList(std::list<RsPgpId> &ids)
|
||||||
{
|
{
|
||||||
return getGPGFilteredList(ids,&filter_OwnSigned);
|
return getGPGFilteredList(ids,&filter_OwnSigned);
|
||||||
}
|
}
|
||||||
|
@ -504,9 +529,9 @@ bool AuthGPG::getGPGSignedList(std::list<RsPgpId> &ids)
|
||||||
// {
|
// {
|
||||||
// RsStackMutex stack(gpgMtxData); /******* LOCKED ******/
|
// RsStackMutex stack(gpgMtxData); /******* LOCKED ******/
|
||||||
// #ifdef LIMIT_CERTIFICATE_SIZE
|
// #ifdef LIMIT_CERTIFICATE_SIZE
|
||||||
// certificate = PGPHandler::SaveCertificateToString(RsPgpId(id),false) ;
|
// certificate = instance()->mPgpHandler->SaveCertificateToString(RsPgpId(id),false) ;
|
||||||
// #else
|
// #else
|
||||||
// certificate = PGPHandler::SaveCertificateToString(RsPgpId(id),true) ;
|
// certificate = instance()->mPgpHandler->SaveCertificateToString(RsPgpId(id),true) ;
|
||||||
// #endif
|
// #endif
|
||||||
//
|
//
|
||||||
// // #ifdef LIMIT_CERTIFICATE_SIZE
|
// // #ifdef LIMIT_CERTIFICATE_SIZE
|
||||||
|
@ -528,20 +553,20 @@ bool AuthGPG::getGPGSignedList(std::list<RsPgpId> &ids)
|
||||||
|
|
||||||
|
|
||||||
/* SKTAN : do not know how to use std::string id */
|
/* SKTAN : do not know how to use std::string id */
|
||||||
std::string AuthGPG::SaveCertificateToString(const RsPgpId &id,bool include_signatures)
|
std::string AuthPGP::SaveCertificateToString(const RsPgpId &id,bool include_signatures)
|
||||||
{
|
{
|
||||||
RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/
|
RsStackMutex stack(instance()->gpgMtxEngine); /******* LOCKED ******/
|
||||||
|
|
||||||
return PGPHandler::SaveCertificateToString(id,include_signatures) ;
|
return instance()->mPgpHandler->SaveCertificateToString(id,include_signatures) ;
|
||||||
}
|
}
|
||||||
/* import to GnuPG and other Certificates */
|
/* import to GnuPG and other Certificates */
|
||||||
bool AuthGPG::LoadPGPKeyFromBinaryData(const unsigned char *data,uint32_t data_len, RsPgpId& gpg_id,std::string& error_string)
|
bool AuthPGP::LoadPGPKeyFromBinaryData(const unsigned char *data,uint32_t data_len, RsPgpId& gpg_id,std::string& error_string)
|
||||||
{
|
{
|
||||||
RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/
|
RsStackMutex stack(instance()->gpgMtxEngine); /******* LOCKED ******/
|
||||||
|
|
||||||
if(PGPHandler::LoadCertificateFromBinaryData(data,data_len,gpg_id,error_string))
|
if(instance()->mPgpHandler->LoadCertificateFromBinaryData(data,data_len,gpg_id,error_string))
|
||||||
{
|
{
|
||||||
updateOwnSignatureFlag(gpg_id,mOwnGpgId) ;
|
instance()->mPgpHandler->updateOwnSignatureFlag(gpg_id,instance()->mOwnGpgId) ;
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,13 +574,13 @@ bool AuthGPG::LoadPGPKeyFromBinaryData(const unsigned char *data,uint32_t data_l
|
||||||
}
|
}
|
||||||
|
|
||||||
/* import to GnuPG and other Certificates */
|
/* import to GnuPG and other Certificates */
|
||||||
bool AuthGPG::LoadCertificateFromString(const std::string &str, RsPgpId& gpg_id,std::string& error_string)
|
bool AuthPGP::LoadCertificateFromString(const std::string &str, RsPgpId& gpg_id,std::string& error_string)
|
||||||
{
|
{
|
||||||
RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/
|
RsStackMutex stack(instance()->gpgMtxEngine); /******* LOCKED ******/
|
||||||
|
|
||||||
if(PGPHandler::LoadCertificateFromString(str,gpg_id,error_string))
|
if(instance()->mPgpHandler->LoadCertificateFromString(str,gpg_id,error_string))
|
||||||
{
|
{
|
||||||
updateOwnSignatureFlag(gpg_id,mOwnGpgId) ;
|
instance()->mPgpHandler->updateOwnSignatureFlag(gpg_id,instance()->mOwnGpgId) ;
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -576,7 +601,7 @@ bool AuthGPG::LoadCertificateFromString(const std::string &str, RsPgpId& gpg_id,
|
||||||
/*************************************/
|
/*************************************/
|
||||||
|
|
||||||
/* These take PGP Ids */
|
/* These take PGP Ids */
|
||||||
bool AuthGPG::AllowConnection(const RsPgpId& gpg_id, bool accept)
|
bool AuthPGP::AllowConnection(const RsPgpId& gpg_id, bool accept)
|
||||||
{
|
{
|
||||||
#ifdef GPG_DEBUG
|
#ifdef GPG_DEBUG
|
||||||
std::cerr << "AuthGPG::AllowConnection(" << gpg_id << ")" << std::endl;
|
std::cerr << "AuthGPG::AllowConnection(" << gpg_id << ")" << std::endl;
|
||||||
|
@ -584,11 +609,11 @@ bool AuthGPG::AllowConnection(const RsPgpId& gpg_id, bool accept)
|
||||||
|
|
||||||
/* Was a "Reload Certificates" here -> be shouldn't be needed -> and very expensive, try without. */
|
/* Was a "Reload Certificates" here -> be shouldn't be needed -> and very expensive, try without. */
|
||||||
{
|
{
|
||||||
RsStackMutex stack(gpgMtxData);
|
RsStackMutex stack(instance()->gpgMtxData);
|
||||||
PGPHandler::setAcceptConnexion(gpg_id,accept) ;
|
instance()->mPgpHandler->setAcceptConnexion(gpg_id,accept) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
IndicateConfigChanged();
|
instance()->IndicateConfigChanged();
|
||||||
|
|
||||||
RsServer::notify()->notifyListChange(NOTIFY_LIST_FRIENDS, accept ? NOTIFY_TYPE_ADD : NOTIFY_TYPE_DEL);
|
RsServer::notify()->notifyListChange(NOTIFY_LIST_FRIENDS, accept ? NOTIFY_TYPE_ADD : NOTIFY_TYPE_DEL);
|
||||||
|
|
||||||
|
@ -596,16 +621,16 @@ bool AuthGPG::AllowConnection(const RsPgpId& gpg_id, bool accept)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* These take PGP Ids */
|
/* These take PGP Ids */
|
||||||
bool AuthGPG::SignCertificateLevel0(const RsPgpId &id)
|
bool AuthPGP::SignCertificateLevel0(const RsPgpId &id)
|
||||||
{
|
{
|
||||||
#ifdef GPG_DEBUG
|
#ifdef GPG_DEBUG
|
||||||
std::cerr << "AuthGPG::SignCertificat(" << id << ")" << std::endl;
|
std::cerr << "AuthGPG::SignCertificat(" << id << ")" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return privateSignCertificate(id) ;
|
return instance()->privateSignCertificate(id) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthGPG::RevokeCertificate(const RsPgpId &id)
|
bool AuthPGP::RevokeCertificate(const RsPgpId &id)
|
||||||
{
|
{
|
||||||
/* remove unused parameter warnings */
|
/* remove unused parameter warnings */
|
||||||
(void) id;
|
(void) id;
|
||||||
|
@ -617,46 +642,59 @@ bool AuthGPG::RevokeCertificate(const RsPgpId &id)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthGPG::TrustCertificate(const RsPgpId& id, int trustlvl)
|
bool AuthPGP::TrustCertificate(const RsPgpId& id, int trustlvl)
|
||||||
{
|
{
|
||||||
#ifdef GPG_DEBUG
|
#ifdef GPG_DEBUG
|
||||||
std::cerr << "AuthGPG::TrustCertificate(" << id << ", " << trustlvl << ")" << std::endl;
|
std::cerr << "AuthGPG::TrustCertificate(" << id << ", " << trustlvl << ")" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
return privateTrustCertificate(id, trustlvl) ;
|
return instance()->privateTrustCertificate(id, trustlvl) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthGPG::encryptDataBin(const RsPgpId& pgp_id,const void *data, unsigned int datalen, unsigned char *sign, unsigned int *signlen)
|
bool AuthPGP::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) ;
|
return instance()->mPgpHandler->encryptDataBin(RsPgpId(pgp_id),data,datalen,sign,signlen) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthGPG::decryptDataBin(const void *data, unsigned int datalen, unsigned char *sign, unsigned int *signlen)
|
bool AuthPGP::decryptDataBin(const void *data, unsigned int datalen, unsigned char *sign, unsigned int *signlen)
|
||||||
{
|
{
|
||||||
return PGPHandler::decryptDataBin(mOwnGpgId,data,datalen,sign,signlen) ;
|
return instance()->mPgpHandler->decryptDataBin(instance()->mOwnGpgId,data,datalen,sign,signlen) ;
|
||||||
}
|
}
|
||||||
bool AuthGPG::SignDataBin(const void *data, unsigned int datalen, unsigned char *sign, unsigned int *signlen, std::string reason /*= ""*/)
|
bool AuthPGP::SignDataBin(const void *data, unsigned int datalen, unsigned char *sign, unsigned int *signlen, std::string reason /*= ""*/)
|
||||||
{
|
{
|
||||||
return DoOwnSignature(data, datalen, sign, signlen, reason);
|
return instance()->DoOwnSignature(data, datalen, sign, signlen, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthGPG::VerifySignBin(const void *data, uint32_t datalen, unsigned char *sign, unsigned int signlen, const PGPFingerprintType& withfingerprint)
|
bool AuthPGP::exportPublicKey( const RsPgpId& id, unsigned char*& mem_block, size_t& mem_size, bool armoured, bool include_signatures )
|
||||||
{
|
{
|
||||||
return VerifySignature(data, datalen, sign, signlen, withfingerprint);
|
return instance()->mPgpHandler->exportPublicKey(id,mem_block,mem_size,armoured,include_signatures);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AuthPGP::isPgpPubKeyAvailable(const RsPgpId& pgp_id)
|
||||||
|
{
|
||||||
|
return instance()->mPgpHandler->isPgpPubKeyAvailable(pgp_id);
|
||||||
|
}
|
||||||
|
bool AuthPGP::getKeyFingerprint(const RsPgpId& id,PGPFingerprintType& fp)
|
||||||
|
{
|
||||||
|
return instance()->mPgpHandler->getKeyFingerprint(id,fp);
|
||||||
|
}
|
||||||
|
bool AuthPGP::VerifySignBin(const void *data, uint32_t datalen, unsigned char *sign, unsigned int signlen, const PGPFingerprintType& withfingerprint)
|
||||||
|
{
|
||||||
|
return instance()->VerifySignature(data, datalen, sign, signlen, withfingerprint);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sign/Trust stuff */
|
/* Sign/Trust stuff */
|
||||||
|
|
||||||
int AuthGPG::privateSignCertificate(const RsPgpId &id)
|
int AuthPGP::privateSignCertificate(const RsPgpId &id)
|
||||||
{
|
{
|
||||||
RsStackMutex stack(gpgMtxData); /******* LOCKED ******/
|
RsStackMutex stack(gpgMtxData); /******* LOCKED ******/
|
||||||
|
|
||||||
int ret = PGPHandler::privateSignCertificate(mOwnGpgId,id) ;
|
int ret = mPgpHandler->privateSignCertificate(mOwnGpgId,id) ;
|
||||||
_force_sync_database = true ;
|
_force_sync_database = true ;
|
||||||
return ret ;
|
return ret ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* revoke the signature on Certificate */
|
/* revoke the signature on Certificate */
|
||||||
int AuthGPG::privateRevokeCertificate(const RsPgpId &/*id*/)
|
int AuthPGP::privateRevokeCertificate(const RsPgpId &/*id*/)
|
||||||
{
|
{
|
||||||
//RsStackMutex stack(gpgMtx); /******* LOCKED ******/
|
//RsStackMutex stack(gpgMtx); /******* LOCKED ******/
|
||||||
std::cerr << __PRETTY_FUNCTION__ << ": not implemented!" << std::endl;
|
std::cerr << __PRETTY_FUNCTION__ << ": not implemented!" << std::endl;
|
||||||
|
@ -664,7 +702,7 @@ int AuthGPG::privateRevokeCertificate(const RsPgpId &/*id*/)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AuthGPG::privateTrustCertificate(const RsPgpId& id, int trustlvl)
|
int AuthPGP::privateTrustCertificate(const RsPgpId& id, int trustlvl)
|
||||||
{
|
{
|
||||||
RsStackMutex stack(gpgMtxData); /******* LOCKED ******/
|
RsStackMutex stack(gpgMtxData); /******* LOCKED ******/
|
||||||
|
|
||||||
|
@ -672,10 +710,10 @@ int AuthGPG::privateTrustCertificate(const RsPgpId& id, int trustlvl)
|
||||||
// The trust level is only a user-defined property that has nothing to
|
// The trust level is only a user-defined property that has nothing to
|
||||||
// do with the fact that we allow connections or not.
|
// do with the fact that we allow connections or not.
|
||||||
|
|
||||||
if(!isGPGAccepted(id))
|
if(!isPGPAccepted(id))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
int res = PGPHandler::privateTrustCertificate(id,trustlvl) ;
|
int res = instance()->mPgpHandler->privateTrustCertificate(id,trustlvl) ;
|
||||||
_force_sync_database = true ;
|
_force_sync_database = true ;
|
||||||
return res ;
|
return res ;
|
||||||
}
|
}
|
||||||
|
@ -684,20 +722,24 @@ int AuthGPG::privateTrustCertificate(const RsPgpId& id, int trustlvl)
|
||||||
// -------------------------------- Config functions ------------------------------ //
|
// -------------------------------- Config functions ------------------------------ //
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
//
|
//
|
||||||
RsSerialiser *AuthGPG::setupSerialiser()
|
RsSerialiser *AuthPGP::setupSerialiser()
|
||||||
{
|
{
|
||||||
RsSerialiser *rss = new RsSerialiser ;
|
RsSerialiser *rss = new RsSerialiser ;
|
||||||
rss->addSerialType(new RsGeneralConfigSerialiser());
|
rss->addSerialType(new RsGeneralConfigSerialiser());
|
||||||
return rss ;
|
return rss ;
|
||||||
}
|
}
|
||||||
|
bool AuthPGP::isPGPAccepted(const RsPgpId& id)
|
||||||
|
{
|
||||||
|
return instance()->mPgpHandler->isGPGAccepted(id);
|
||||||
|
}
|
||||||
|
|
||||||
bool AuthGPG::saveList(bool& cleanup, std::list<RsItem*>& lst)
|
bool AuthPGP::saveList(bool& cleanup, std::list<RsItem*>& lst)
|
||||||
{
|
{
|
||||||
#ifdef GPG_DEBUG
|
#ifdef GPG_DEBUG
|
||||||
std::cerr << "AuthGPG::saveList() called" << std::endl ;
|
std::cerr << "AuthGPG::saveList() called" << std::endl ;
|
||||||
#endif
|
#endif
|
||||||
std::list<RsPgpId> ids ;
|
std::list<RsPgpId> ids ;
|
||||||
getGPGAcceptedList(ids) ; // needs to be done before the lock
|
getPgpAcceptedList(ids) ; // needs to be done before the lock
|
||||||
|
|
||||||
RsStackMutex stack(gpgMtxData); /******* LOCKED ******/
|
RsStackMutex stack(gpgMtxData); /******* LOCKED ******/
|
||||||
|
|
||||||
|
@ -722,7 +764,7 @@ bool AuthGPG::saveList(bool& cleanup, std::list<RsItem*>& lst)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthGPG::loadList(std::list<RsItem*>& load)
|
bool AuthPGP::loadList(std::list<RsItem*>& load)
|
||||||
{
|
{
|
||||||
#ifdef GPG_DEBUG
|
#ifdef GPG_DEBUG
|
||||||
std::cerr << "AuthGPG::loadList() Item Count: " << load.size() << std::endl;
|
std::cerr << "AuthGPG::loadList() Item Count: " << load.size() << std::endl;
|
||||||
|
@ -745,7 +787,7 @@ bool AuthGPG::loadList(std::list<RsItem*>& load)
|
||||||
std::list<RsTlvKeyValue>::iterator kit;
|
std::list<RsTlvKeyValue>::iterator kit;
|
||||||
for(kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit)
|
for(kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit)
|
||||||
if (kit->key != mOwnGpgId.toStdString())
|
if (kit->key != mOwnGpgId.toStdString())
|
||||||
PGPHandler::setAcceptConnexion(RsPgpId(kit->key), (kit->value == "TRUE"));
|
instance()->mPgpHandler->setAcceptConnexion(RsPgpId(kit->key), (kit->value == "TRUE"));
|
||||||
}
|
}
|
||||||
delete (*it);
|
delete (*it);
|
||||||
}
|
}
|
||||||
|
@ -753,16 +795,16 @@ bool AuthGPG::loadList(std::list<RsItem*>& load)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthGPG::addService(AuthGPGService *service)
|
bool AuthPGP::addService(AuthGPGService *service)
|
||||||
{
|
{
|
||||||
RsStackMutex stack(gpgMtxService); /********* LOCKED *********/
|
RsStackMutex stack(instance()->gpgMtxService); /********* LOCKED *********/
|
||||||
|
|
||||||
if (std::find(services.begin(), services.end(), service) != services.end()) {
|
if (std::find(instance()->services.begin(), instance()->services.end(), service) != instance()->services.end()) {
|
||||||
/* it exists already! */
|
/* it exists already! */
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
services.push_back(service);
|
instance()->services.push_back(service);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
|
|
||||||
#include "util/rsthreads.h"
|
#include "util/rsthreads.h"
|
||||||
#include "pqi/p3cfgmgr.h"
|
#include "pqi/p3cfgmgr.h"
|
||||||
#include "pgp/pgphandler.h"
|
#include "pgp/openpgpsdkhandler.h"
|
||||||
|
|
||||||
#define MAX_GPG_SIGNATURE_SIZE 4096
|
#define MAX_GPG_SIGNATURE_SIZE 4096
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ public:
|
||||||
virtual void setGPGOperation(AuthGPGOperation *operation) = 0;
|
virtual void setGPGOperation(AuthGPGOperation *operation) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AuthGPG: public p3Config, public RsTickingThread, public PGPHandler
|
class AuthPGP: public p3Config, public RsTickingThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void init(const std::string& path_to_pubring,
|
static void init(const std::string& path_to_pubring,
|
||||||
|
@ -97,8 +97,11 @@ public:
|
||||||
const std::string& path_to_trustdb,
|
const std::string& path_to_trustdb,
|
||||||
const std::string& pgp_lock_file);
|
const std::string& pgp_lock_file);
|
||||||
|
|
||||||
|
static void registerToConfigMgr(const std::string& fname,p3ConfigMgr *CfgMgr);
|
||||||
static void exit();
|
static void exit();
|
||||||
static AuthGPG *getAuthGPG() { return _instance ; }
|
|
||||||
|
static bool isPGPId(const RsPgpId& id) ;
|
||||||
|
static bool isPGPAccepted(const RsPgpId& id) ;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ids list of gpg certificate ids (note, not the actual certificates)
|
* @param ids list of gpg certificate ids (note, not the actual certificates)
|
||||||
|
@ -118,7 +121,7 @@ public:
|
||||||
* (see storage at the end of the class)
|
* (see storage at the end of the class)
|
||||||
*
|
*
|
||||||
****/
|
****/
|
||||||
virtual bool active();
|
static bool active();
|
||||||
|
|
||||||
// /* Initialize */
|
// /* Initialize */
|
||||||
// virtual bool InitAuth ();
|
// virtual bool InitAuth ();
|
||||||
|
@ -126,8 +129,11 @@ public:
|
||||||
|
|
||||||
/* Init by generating new Own PGP Cert, or selecting existing PGP Cert */
|
/* Init by generating new Own PGP Cert, or selecting existing PGP Cert */
|
||||||
|
|
||||||
virtual int GPGInit(const RsPgpId &ownId);
|
static int PgpInit(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);
|
static bool GeneratePgpCertificate(const std::string& name, const std::string& email, const std::string& passwd, RsPgpId &pgpId, const int keynumbits, std::string &errString);
|
||||||
|
|
||||||
|
static bool getPgpDetailsFromBinaryBlock(const unsigned char *mem,size_t mem_size,RsPgpId& key_id, std::string& name, std::list<RsPgpId>& signers) ;
|
||||||
|
static int availablePgpCertificatesWithPrivateKeys(std::list<RsPgpId>& pgpIds);
|
||||||
|
|
||||||
/*********************************************************************************/
|
/*********************************************************************************/
|
||||||
/************************* STAGE 3 ***********************************************/
|
/************************* STAGE 3 ***********************************************/
|
||||||
|
@ -140,29 +146,33 @@ public:
|
||||||
* provide access to details in cache list.
|
* provide access to details in cache list.
|
||||||
*
|
*
|
||||||
****/
|
****/
|
||||||
virtual std::string getGPGName(const RsPgpId &pgp_id,bool *success = NULL);
|
static std::string getPgpName(const RsPgpId &pgp_id,bool *success = NULL);
|
||||||
virtual std::string getGPGEmail(const RsPgpId &pgp_id,bool *success = NULL);
|
static std::string getPgpEmail(const RsPgpId &pgp_id,bool *success = NULL);
|
||||||
|
|
||||||
|
static bool exportPublicKey( const RsPgpId& id, unsigned char*& mem_block, size_t& mem_size, bool armoured, bool include_signatures );
|
||||||
|
|
||||||
/* PGP web of trust management */
|
/* PGP web of trust management */
|
||||||
virtual const RsPgpId& getGPGOwnId();
|
static const RsPgpId& getPgpOwnId();
|
||||||
virtual std::string getGPGOwnName();
|
static std::string getPgpOwnName();
|
||||||
|
|
||||||
//virtual std::string getGPGOwnEmail();
|
//virtual std::string getGPGOwnEmail();
|
||||||
virtual bool isKeySupported(const RsPgpId &id) const ;
|
static bool getKeyFingerprint(const RsPgpId& id,PGPFingerprintType& fp) ;
|
||||||
virtual bool haveSecretKey(const RsPgpId &id) const ;
|
static bool isKeySupported(const RsPgpId &id) ;
|
||||||
virtual bool getGPGDetails(const RsPgpId& id, RsPeerDetails &d);
|
static bool isPgpPubKeyAvailable(const RsPgpId& pgp_id);
|
||||||
virtual bool getGPGAllList(std::list<RsPgpId> &ids);
|
static bool haveSecretKey(const RsPgpId &id) ;
|
||||||
virtual bool getGPGValidList(std::list<RsPgpId> &ids);
|
static bool getPgpDetails(const RsPgpId& id, RsPeerDetails &d);
|
||||||
virtual bool getGPGAcceptedList(std::list<RsPgpId> &ids);
|
static bool getPgpAllList(std::list<RsPgpId> &ids);
|
||||||
virtual bool getGPGSignedList(std::list<RsPgpId> &ids);
|
static bool getPgpValidList(std::list<RsPgpId> &ids);
|
||||||
virtual bool importProfile(const std::string& filename,RsPgpId& gpg_id,std::string& import_error) ;
|
static bool getPgpAcceptedList(std::list<RsPgpId> &ids);
|
||||||
virtual bool importProfileFromString(const std::string& data,RsPgpId& gpg_id,std::string& import_error) ;
|
static bool getPgpSignedList(std::list<RsPgpId> &ids);
|
||||||
virtual bool exportProfile(const std::string& filename,const RsPgpId& gpg_id) ;
|
static bool importProfile(const std::string& filename,RsPgpId& gpg_id,std::string& import_error) ;
|
||||||
virtual bool exportIdentityToString(
|
static bool importProfileFromString(const std::string& data,RsPgpId& gpg_id,std::string& import_error) ;
|
||||||
|
static bool exportProfile(const std::string& filename,const RsPgpId& gpg_id) ;
|
||||||
|
static bool exportIdentityToString(
|
||||||
std::string& data, const RsPgpId& pgpId, bool includeSignatures,
|
std::string& data, const RsPgpId& pgpId, bool includeSignatures,
|
||||||
std::string& errorMsg );
|
std::string& errorMsg );
|
||||||
|
|
||||||
virtual bool removeKeysFromPGPKeyring(const std::set<RsPgpId> &pgp_ids,std::string& backup_file,uint32_t& error_code) ;
|
static bool removeKeysFromPGPKeyring(const std::set<RsPgpId> &pgp_ids,std::string& backup_file,uint32_t& error_code) ;
|
||||||
|
|
||||||
/*********************************************************************************/
|
/*********************************************************************************/
|
||||||
/************************* STAGE 4 ***********************************************/
|
/************************* STAGE 4 ***********************************************/
|
||||||
|
@ -171,9 +181,9 @@ public:
|
||||||
* STAGE 4: Loading and Saving Certificates. (Strings and Files)
|
* STAGE 4: Loading and Saving Certificates. (Strings and Files)
|
||||||
*
|
*
|
||||||
****/
|
****/
|
||||||
virtual bool LoadCertificateFromString(const std::string &pem, RsPgpId& gpg_id,std::string& error_string);
|
static 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);
|
static 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) ;
|
static std::string SaveCertificateToString(const RsPgpId &id,bool include_signatures) ;
|
||||||
|
|
||||||
// Cached certificates.
|
// Cached certificates.
|
||||||
//bool getCachedGPGCertificate(const RsPgpId &id, std::string &certificate);
|
//bool getCachedGPGCertificate(const RsPgpId &id, std::string &certificate);
|
||||||
|
@ -188,12 +198,12 @@ public:
|
||||||
* done in gpgroot already.
|
* done in gpgroot already.
|
||||||
*
|
*
|
||||||
****/
|
****/
|
||||||
virtual bool AllowConnection(const RsPgpId &gpg_id, bool accept);
|
static bool AllowConnection(const RsPgpId &gpg_id, bool accept);
|
||||||
|
|
||||||
virtual bool SignCertificateLevel0(const RsPgpId &id);
|
static bool SignCertificateLevel0(const RsPgpId &id);
|
||||||
virtual bool RevokeCertificate(const RsPgpId &id); /* Particularly hard - leave for later */
|
static 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
|
static bool TrustCertificate(const RsPgpId& id, int trustlvl); //trustlvl is 2 for none, 3 for marginal and 4 for full trust
|
||||||
|
|
||||||
/*********************************************************************************/
|
/*********************************************************************************/
|
||||||
/************************* STAGE 7 ***********************************************/
|
/************************* STAGE 7 ***********************************************/
|
||||||
|
@ -204,39 +214,39 @@ public:
|
||||||
* There should also be Encryption Functions... (do later).
|
* 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 = "");
|
static 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);
|
static 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);
|
static 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);
|
static 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);
|
static 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);
|
static bool decryptTextFromFile( std::string& text,const std::string& filename);
|
||||||
virtual bool encryptTextToFile (const std::string& text,const std::string& filename);
|
static bool encryptTextToFile (const std::string& text,const std::string& filename);
|
||||||
|
|
||||||
// virtual bool decryptTextFromString( std::string& encrypted_text,std::string& clear_string);
|
// 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);
|
// virtual bool encryptTextToString (const std::string& pgp_id,const std::string& clear_text,std::string& encrypted_string);
|
||||||
|
|
||||||
bool getGPGFilteredList(std::list<RsPgpId>& list,bool (*filter)(const PGPCertificateInfo&) = NULL) ;
|
static bool getGPGFilteredList(std::list<RsPgpId>& list,bool (*filter)(const PGPCertificateInfo&) = NULL) ;
|
||||||
|
|
||||||
//END of PGP public functions
|
//END of PGP public functions
|
||||||
|
|
||||||
/* GPG service */
|
/* GPG service */
|
||||||
virtual bool addService(AuthGPGService *service) ;
|
static bool addService(AuthGPGService *service) ;
|
||||||
|
|
||||||
// This is for debug purpose only. Don't use it !!
|
// This is for debug purpose only. Don't use it !!
|
||||||
static void setAuthGPG_debug(AuthGPG *auth_gpg) { _instance = auth_gpg ; }
|
static void setAuthGPG_debug(AuthPGP *auth_gpg) { _instance = auth_gpg ; }
|
||||||
|
|
||||||
protected:
|
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);
|
AuthPGP(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();
|
virtual ~AuthPGP();
|
||||||
|
|
||||||
/*****************************************************************/
|
/*****************************************************************/
|
||||||
/*********************** p3config ******************************/
|
/*********************** p3config ******************************/
|
||||||
/* Key Functions to be overloaded for Full Configuration */
|
/* Key Functions to be overloaded for Full Configuration */
|
||||||
virtual RsSerialiser *setupSerialiser();
|
virtual RsSerialiser *setupSerialiser() override;
|
||||||
virtual bool saveList(bool &cleanup, std::list<RsItem *>&);
|
virtual bool saveList(bool &cleanup, std::list<RsItem *>&) override;
|
||||||
virtual bool loadList(std::list<RsItem *>& load);
|
virtual bool loadList(std::list<RsItem *>& load) override;
|
||||||
/*****************************************************************/
|
/*****************************************************************/
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -274,8 +284,7 @@ private:
|
||||||
void threadTick() override; /// @see RsTickingThread
|
void threadTick() override; /// @see RsTickingThread
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static AuthPGP *instance();
|
||||||
static AuthGPG *instance_gpg; // pointeur vers le singleton
|
|
||||||
|
|
||||||
RsMutex gpgMtxService;
|
RsMutex gpgMtxService;
|
||||||
RsMutex gpgMtxEngine;
|
RsMutex gpgMtxEngine;
|
||||||
|
@ -290,6 +299,8 @@ private:
|
||||||
|
|
||||||
rstime_t mStoreKeyTime;
|
rstime_t mStoreKeyTime;
|
||||||
|
|
||||||
|
PGPHandler *mPgpHandler;
|
||||||
|
|
||||||
RsPgpId mOwnGpgId;
|
RsPgpId mOwnGpgId;
|
||||||
bool gpgKeySelected;
|
bool gpgKeySelected;
|
||||||
bool _force_sync_database ;
|
bool _force_sync_database ;
|
||||||
|
@ -297,7 +308,7 @@ private:
|
||||||
|
|
||||||
std::list<AuthGPGService*> services ;
|
std::list<AuthGPGService*> services ;
|
||||||
|
|
||||||
static AuthGPG *_instance ;
|
static AuthPGP *_instance ;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -759,8 +759,7 @@ X509 *AuthSSLimpl::SignX509ReqWithGPG(X509_REQ *req, long /*days*/)
|
||||||
//long version = 0x00;
|
//long version = 0x00;
|
||||||
unsigned long chtype = MBSTRING_UTF8;
|
unsigned long chtype = MBSTRING_UTF8;
|
||||||
X509_NAME *issuer_name = X509_NAME_new();
|
X509_NAME *issuer_name = X509_NAME_new();
|
||||||
X509_NAME_add_entry_by_txt(issuer_name, "CN", chtype,
|
X509_NAME_add_entry_by_txt(issuer_name, "CN", chtype, (unsigned char *) AuthPGP::getPgpOwnId().toStdString().c_str(), -1, -1, 0);
|
||||||
(unsigned char *) AuthGPG::getAuthGPG()->getGPGOwnId().toStdString().c_str(), -1, -1, 0);
|
|
||||||
/****
|
/****
|
||||||
X509_NAME_add_entry_by_NID(issuer_name, 48, 0,
|
X509_NAME_add_entry_by_NID(issuer_name, 48, 0,
|
||||||
(unsigned char *) "email@email.com", -1, -1, 0);
|
(unsigned char *) "email@email.com", -1, -1, 0);
|
||||||
|
@ -770,7 +769,7 @@ X509 *AuthSSLimpl::SignX509ReqWithGPG(X509_REQ *req, long /*days*/)
|
||||||
(unsigned char *) "loc", -1, -1, 0);
|
(unsigned char *) "loc", -1, -1, 0);
|
||||||
****/
|
****/
|
||||||
|
|
||||||
std::cerr << "AuthSSLimpl::SignX509Req() Issuer name: " << AuthGPG::getAuthGPG()->getGPGOwnId().toStdString() << std::endl;
|
std::cerr << "AuthSSLimpl::SignX509Req() Issuer name: " << AuthPGP::getPgpOwnId().toStdString() << std::endl;
|
||||||
|
|
||||||
#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_002
|
#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_002
|
||||||
static const uint64_t CERTIFICATE_SERIAL_NUMBER = RS_CERTIFICATE_VERSION_NUMBER_07_0001 ;
|
static const uint64_t CERTIFICATE_SERIAL_NUMBER = RS_CERTIFICATE_VERSION_NUMBER_07_0001 ;
|
||||||
|
@ -945,7 +944,7 @@ X509 *AuthSSLimpl::SignX509ReqWithGPG(X509_REQ *req, long /*days*/)
|
||||||
std::cerr << "Buffers Allocated" << std::endl;
|
std::cerr << "Buffers Allocated" << std::endl;
|
||||||
|
|
||||||
/* NOW Sign via GPG Functions */
|
/* NOW Sign via GPG Functions */
|
||||||
if (!AuthGPG::getAuthGPG()->SignDataBin(buf_in, inl, buf_sigout, (unsigned int *) &sigoutl,"AuthSSLimpl::SignX509ReqWithGPG()"))
|
if (!AuthPGP::SignDataBin(buf_in, inl, buf_sigout, (unsigned int *) &sigoutl,"AuthSSLimpl::SignX509ReqWithGPG()"))
|
||||||
{
|
{
|
||||||
sigoutl = 0;
|
sigoutl = 0;
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -1040,7 +1039,7 @@ bool AuthSSLimpl::AuthX509WithGPG(X509 *x509,bool verbose, uint32_t& diagnostic)
|
||||||
{
|
{
|
||||||
RsPgpId issuer = RsX509Cert::getCertIssuer(*x509);
|
RsPgpId issuer = RsX509Cert::getCertIssuer(*x509);
|
||||||
RsPeerDetails pd;
|
RsPeerDetails pd;
|
||||||
if (!AuthGPG::getAuthGPG()->getGPGDetails(issuer, pd))
|
if (!AuthPGP::getPgpDetails(issuer, pd))
|
||||||
{
|
{
|
||||||
RsInfo() << __PRETTY_FUNCTION__ << " X509 NOT authenticated : "
|
RsInfo() << __PRETTY_FUNCTION__ << " X509 NOT authenticated : "
|
||||||
<< "AuthGPG::getAuthGPG()->getGPGDetails(" << issuer
|
<< "AuthGPG::getAuthGPG()->getGPGDetails(" << issuer
|
||||||
|
@ -1185,9 +1184,7 @@ bool AuthSSLimpl::AuthX509WithGPG(X509 *x509,bool verbose, uint32_t& diagnostic)
|
||||||
|
|
||||||
// passed, verify the signature itself
|
// passed, verify the signature itself
|
||||||
|
|
||||||
if (!AuthGPG::getAuthGPG()->VerifySignBin(
|
if (!AuthPGP::VerifySignBin( signed_data, signed_data_length, signature->data, static_cast<unsigned int>(signature->length), pd.fpr ))
|
||||||
signed_data, signed_data_length, signature->data,
|
|
||||||
static_cast<unsigned int>(signature->length), pd.fpr ))
|
|
||||||
{
|
{
|
||||||
diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE;
|
diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE;
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -1383,7 +1380,7 @@ int AuthSSLimpl::VerifyX509Callback(int /*preverify_ok*/, X509_STORE_CTX* ctx)
|
||||||
std::cerr << "******* VerifyX509Callback cert: " << std::hex << ctx->cert <<std::dec << std::endl;
|
std::cerr << "******* VerifyX509Callback cert: " << std::hex << ctx->cert <<std::dec << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ( !isSslOnlyFriend && pgpId != AuthGPG::getAuthGPG()->getGPGOwnId() && !AuthGPG::getAuthGPG()->isGPGAccepted(pgpId) )
|
if ( !isSslOnlyFriend && pgpId != AuthPGP::getPgpOwnId() && !AuthPGP::isPGPAccepted(pgpId) )
|
||||||
{
|
{
|
||||||
std::string errMsg = "Connection attempt signed by PGP key id: " +
|
std::string errMsg = "Connection attempt signed by PGP key id: " +
|
||||||
pgpId.toStdString() + " not accepted because it is not"
|
pgpId.toStdString() + " not accepted because it is not"
|
||||||
|
|
|
@ -812,11 +812,11 @@ int p3PeerMgrIMPL::getFriendCount(bool ssl, bool online)
|
||||||
|
|
||||||
// count all gpg id's
|
// count all gpg id's
|
||||||
std::list<RsPgpId> gpgIds;
|
std::list<RsPgpId> gpgIds;
|
||||||
AuthGPG::getAuthGPG()->getGPGAcceptedList(gpgIds);
|
AuthPGP::getPgpAcceptedList(gpgIds);
|
||||||
|
|
||||||
// add own gpg id, if we have more than one location
|
// add own gpg id, if we have more than one location
|
||||||
std::list<RsPeerId> ownSslIds;
|
std::list<RsPeerId> ownSslIds;
|
||||||
getAssociatedPeers(AuthGPG::getAuthGPG()->getGPGOwnId(), ownSslIds);
|
getAssociatedPeers(AuthPGP::getPgpOwnId(), ownSslIds);
|
||||||
|
|
||||||
return gpgIds.size() + ((ownSslIds.size() > 0) ? 1 : 0);
|
return gpgIds.size() + ((ownSslIds.size() > 0) ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
@ -962,7 +962,7 @@ bool p3PeerMgrIMPL::addFriend(const RsPeerId& input_id, const RsPgpId& input_gpg
|
||||||
|
|
||||||
// check that the PGP key is known
|
// check that the PGP key is known
|
||||||
|
|
||||||
if(!AuthGPG::getAuthGPG()->isGPGId(gpg_id))
|
if(!AuthPGP::isPGPId(gpg_id))
|
||||||
{
|
{
|
||||||
RsErr() << "Trying to add SSL id (" << id << ") to be validated with unknown PGP key (" << gpg_id << ". This is a bug!" << std::endl;
|
RsErr() << "Trying to add SSL id (" << id << ") to be validated with unknown PGP key (" << gpg_id << ". This is a bug!" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
|
@ -970,7 +970,7 @@ bool p3PeerMgrIMPL::addFriend(const RsPeerId& input_id, const RsPgpId& input_gpg
|
||||||
|
|
||||||
//Authentication is now tested at connection time, we don't store the ssl cert anymore
|
//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())
|
if (!AuthPGP::isPGPAccepted(gpg_id) && gpg_id != AuthPGP::getPgpOwnId())
|
||||||
{
|
{
|
||||||
#ifdef PEER_DEBUG
|
#ifdef PEER_DEBUG
|
||||||
std::cerr << "p3PeerMgrIMPL::addFriend() gpg is not accepted" << std::endl;
|
std::cerr << "p3PeerMgrIMPL::addFriend() gpg is not accepted" << std::endl;
|
||||||
|
@ -1024,7 +1024,7 @@ bool p3PeerMgrIMPL::addFriend(const RsPeerId& input_id, const RsPgpId& input_gpg
|
||||||
|
|
||||||
pstate.id = id;
|
pstate.id = id;
|
||||||
pstate.gpg_id = gpg_id;
|
pstate.gpg_id = gpg_id;
|
||||||
pstate.name = AuthGPG::getAuthGPG()->getGPGName(gpg_id);
|
pstate.name = AuthPGP::getPgpName(gpg_id);
|
||||||
|
|
||||||
pstate.vs_disc = vs_disc;
|
pstate.vs_disc = vs_disc;
|
||||||
pstate.vs_dht = vs_dht;
|
pstate.vs_dht = vs_dht;
|
||||||
|
@ -1126,8 +1126,8 @@ bool p3PeerMgrIMPL::addSslOnlyFriend( const RsPeerId& sslId, const RsPgpId& pgp_
|
||||||
* superficially set to true the PGP signature verification would have been
|
* superficially set to true the PGP signature verification would have been
|
||||||
* skipped and the attacker connection would be accepted.
|
* skipped and the attacker connection would be accepted.
|
||||||
* If the PGP key is available add it as full friend. */
|
* If the PGP key is available add it as full friend. */
|
||||||
if(AuthGPG::getAuthGPG()->isPgpPubKeyAvailable(pgp_id))
|
if(AuthPGP::isPgpPubKeyAvailable(pgp_id))
|
||||||
AuthGPG::getAuthGPG()->AllowConnection(pgp_id, true);
|
AuthPGP::AllowConnection(pgp_id, true);
|
||||||
else
|
else
|
||||||
pstate.skip_pgp_signature_validation = true;
|
pstate.skip_pgp_signature_validation = true;
|
||||||
|
|
||||||
|
@ -1398,11 +1398,11 @@ bool p3PeerMgrIMPL::UpdateOwnAddress( const sockaddr_storage& pLocalAddr,
|
||||||
sockaddr_storage_copy(pExtAddr, extAddr);
|
sockaddr_storage_copy(pExtAddr, extAddr);
|
||||||
sockaddr_storage_ipv6_to_ipv4(extAddr);
|
sockaddr_storage_ipv6_to_ipv4(extAddr);
|
||||||
|
|
||||||
//#ifdef PEER_DEBUG
|
#ifdef PEER_DEBUG
|
||||||
std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress("
|
std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress("
|
||||||
<< sockaddr_storage_tostring(localAddr) << ", "
|
<< sockaddr_storage_tostring(localAddr) << ", "
|
||||||
<< sockaddr_storage_tostring(extAddr) << ")" << std::endl;
|
<< sockaddr_storage_tostring(extAddr) << ")" << std::endl;
|
||||||
//#endif
|
#endif
|
||||||
|
|
||||||
if( rsBanList &&
|
if( rsBanList &&
|
||||||
!rsBanList->isAddressAccepted(localAddr,
|
!rsBanList->isAddressAccepted(localAddr,
|
||||||
|
@ -2470,7 +2470,7 @@ bool p3PeerMgrIMPL::loadList(std::list<RsItem *>& load)
|
||||||
setOwnNetworkMode(pitem->netMode);
|
setOwnNetworkMode(pitem->netMode);
|
||||||
setOwnVisState(pitem->vs_disc, pitem->vs_dht);
|
setOwnVisState(pitem->vs_disc, pitem->vs_dht);
|
||||||
|
|
||||||
mOwnState.gpg_id = AuthGPG::getAuthGPG()->getGPGOwnId();
|
mOwnState.gpg_id = AuthPGP::getPgpOwnId();
|
||||||
mOwnState.location = AuthSSL::getAuthSSL()->getOwnLocation();
|
mOwnState.location = AuthSSL::getAuthSSL()->getOwnLocation();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2642,7 +2642,7 @@ bool p3PeerMgrIMPL::loadList(std::list<RsItem *>& load)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for(uint32_t i=0;i<sitem->pgp_ids.size();++i)
|
for(uint32_t i=0;i<sitem->pgp_ids.size();++i)
|
||||||
if(AuthGPG::getAuthGPG()->isGPGAccepted(sitem->pgp_ids[i]) || sitem->pgp_ids[i] == AuthGPG::getAuthGPG()->getGPGOwnId())
|
if(AuthPGP::isPGPAccepted(sitem->pgp_ids[i]) || sitem->pgp_ids[i] == AuthPGP::getPgpOwnId())
|
||||||
{
|
{
|
||||||
mFriendsPermissionFlags[sitem->pgp_ids[i]] = sitem->service_flags[i] ;
|
mFriendsPermissionFlags[sitem->pgp_ids[i]] = sitem->service_flags[i] ;
|
||||||
#ifdef PEER_DEBUG
|
#ifdef PEER_DEBUG
|
||||||
|
@ -2684,7 +2684,7 @@ bool p3PeerMgrIMPL::loadList(std::list<RsItem *>& load)
|
||||||
for(auto group_pair:groupList)
|
for(auto group_pair:groupList)
|
||||||
{
|
{
|
||||||
for(auto profileIdIt(group_pair.second.peerIds.begin());profileIdIt!=group_pair.second.peerIds.end();)
|
for(auto profileIdIt(group_pair.second.peerIds.begin());profileIdIt!=group_pair.second.peerIds.end();)
|
||||||
if(AuthGPG::getAuthGPG()->isGPGAccepted(*profileIdIt) || *profileIdIt == AuthGPG::getAuthGPG()->getGPGOwnId())
|
if(AuthPGP::isPGPAccepted(*profileIdIt) || *profileIdIt == AuthPGP::getPgpOwnId())
|
||||||
++profileIdIt;
|
++profileIdIt;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -46,9 +46,13 @@ void RsFdBinInterface::setSocket(int s)
|
||||||
int flags = fcntl(s,F_GETFL);
|
int flags = fcntl(s,F_GETFL);
|
||||||
|
|
||||||
if(!(flags & O_NONBLOCK))
|
if(!(flags & O_NONBLOCK))
|
||||||
throw std::runtime_error("Trying to use a blocking file descriptor in RsFdBinInterface. This is not going to work!");
|
{
|
||||||
|
RsWarn() << "Trying to use a blocking file descriptor in RsFdBinInterface. This is not going to work! Setting the socket to be non blocking.";
|
||||||
|
unix_fcntl_nonblock(s);
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
// On windows, there is no way to determine whether a socket is blobking or not, so we set it to non blocking whatsoever.
|
// On windows, there is no way to determine whether a socket is blocking or not, so we set it to non blocking whatsoever.
|
||||||
unsigned long int on = 1;
|
unsigned long int on = 1;
|
||||||
ioctlsocket(s, FIONBIO, &on);
|
ioctlsocket(s, FIONBIO, &on);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,15 +21,6 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
#ifdef WINDOWS_SYS
|
|
||||||
# include "util/rswin.h"
|
|
||||||
# include "util/rsmemory.h"
|
|
||||||
# include <ws2tcpip.h>
|
|
||||||
#endif // WINDOWS_SYS
|
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
|
||||||
# include <android/api-level.h>
|
|
||||||
#endif // def __ANDROID__
|
|
||||||
|
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -43,6 +34,28 @@
|
||||||
#include "util/rsnet.h"
|
#include "util/rsnet.h"
|
||||||
#include "util/stacktrace.h"
|
#include "util/stacktrace.h"
|
||||||
|
|
||||||
|
#ifdef WINDOWS_SYS
|
||||||
|
# include "util/rswin.h"
|
||||||
|
# include "util/rsmemory.h"
|
||||||
|
# include <ws2tcpip.h>
|
||||||
|
#endif // WINDOWS_SYS
|
||||||
|
|
||||||
|
/// @See: android_ifaddrs/README.adoc
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
# include <android/api-level.h>
|
||||||
|
#endif // def __ANDROID__
|
||||||
|
|
||||||
|
#ifdef WINDOWS_SYS /* Windows - define errno */
|
||||||
|
int errno;
|
||||||
|
#else /* Windows - define errno */
|
||||||
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __HAIKU__
|
||||||
|
# include <sys/sockio.h>
|
||||||
|
# define IFF_RUNNING 0x0001
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct RsLog::logInfo pqinetzoneInfo = {RsLog::Default, "pqinet"};
|
static struct RsLog::logInfo pqinetzoneInfo = {RsLog::Default, "pqinet"};
|
||||||
#define pqinetzone &pqinetzoneInfo
|
#define pqinetzone &pqinetzoneInfo
|
||||||
|
|
||||||
|
@ -50,21 +63,6 @@ static struct RsLog::logInfo pqinetzoneInfo = {RsLog::Default, "pqinet"};
|
||||||
* #define NET_DEBUG 1
|
* #define NET_DEBUG 1
|
||||||
****/
|
****/
|
||||||
|
|
||||||
#ifdef WINDOWS_SYS /* Windows - define errno */
|
|
||||||
|
|
||||||
int errno;
|
|
||||||
|
|
||||||
#else /* Windows - define errno */
|
|
||||||
|
|
||||||
#include <netdb.h>
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __HAIKU__
|
|
||||||
#include <sys/sockio.h>
|
|
||||||
#define IFF_RUNNING 0x0001
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||||||
#ifndef WINDOWS_SYS
|
#ifndef WINDOWS_SYS
|
||||||
|
|
||||||
|
@ -270,18 +268,16 @@ int inet_aton(const char *name, struct in_addr *addr)
|
||||||
#endif
|
#endif
|
||||||
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||||||
|
|
||||||
|
#include "util/cxx17retrocompat.h"
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#ifdef WINDOWS_SYS
|
#ifdef WINDOWS_SYS
|
||||||
# include <winsock2.h>
|
# include <winsock2.h>
|
||||||
# include <iphlpapi.h>
|
# include <iphlpapi.h>
|
||||||
# pragma comment(lib, "IPHLPAPI.lib")
|
# pragma comment(lib, "IPHLPAPI.lib")
|
||||||
#elif defined(__ANDROID__) && __ANDROID_API__ < 24
|
#elif defined(__ANDROID__) && __ANDROID_API__ < 24
|
||||||
# include <string>
|
/// @See: android_ifaddrs/README.adoc
|
||||||
# include <QString>
|
# include "rs_android/ifaddrs-android.h"
|
||||||
# include <QHostAddress>
|
#else // not WINDOWS => Linux and other unixes
|
||||||
# include <QNetworkInterface>
|
|
||||||
#else // not __ANDROID__ nor WINDOWS => Linux and other unixes
|
|
||||||
# include <ifaddrs.h>
|
# include <ifaddrs.h>
|
||||||
# include <net/if.h>
|
# include <net/if.h>
|
||||||
#endif // WINDOWS_SYS
|
#endif // WINDOWS_SYS
|
||||||
|
@ -324,20 +320,12 @@ bool getLocalAddresses(std::vector<sockaddr_storage>& addrs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(adapter_addresses);
|
free(adapter_addresses);
|
||||||
#elif defined(__ANDROID__) && __ANDROID_API__ < 24
|
#else // not WINDOWS_SYS => Linux and other unixes
|
||||||
for(auto& 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;
|
struct ifaddrs *ifsaddrs, *ifa;
|
||||||
if(getifaddrs(&ifsaddrs) != 0)
|
if(getifaddrs(&ifsaddrs) != 0)
|
||||||
{
|
{
|
||||||
std::cerr << __PRETTY_FUNCTION__ << " FATAL ERROR: " << errno << " "
|
RS_ERR( "getifaddrs failed with: ", errno, " ",
|
||||||
<< strerror(errno) << std::endl;
|
rs_errno_to_condition(errno) );
|
||||||
print_stacktrace();
|
print_stacktrace();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -346,18 +334,19 @@ bool getLocalAddresses(std::vector<sockaddr_storage>& addrs)
|
||||||
{
|
{
|
||||||
sockaddr_storage tmp;
|
sockaddr_storage tmp;
|
||||||
sockaddr_storage_clear(tmp);
|
sockaddr_storage_clear(tmp);
|
||||||
if (sockaddr_storage_copyip(tmp, *reinterpret_cast<sockaddr_storage*>(ifa->ifa_addr)))
|
if(sockaddr_storage_copyip(
|
||||||
|
tmp,
|
||||||
|
*reinterpret_cast<sockaddr_storage*>(ifa->ifa_addr) ))
|
||||||
addrs.push_back(tmp);
|
addrs.push_back(tmp);
|
||||||
}
|
}
|
||||||
freeifaddrs(ifsaddrs);
|
freeifaddrs(ifsaddrs);
|
||||||
#endif // WINDOWS_SYS
|
#endif // WINDOWS_SYS
|
||||||
|
|
||||||
#ifdef NET_DEBUG
|
#ifdef NET_DEBUG
|
||||||
std::list<sockaddr_storage>::iterator it;
|
auto&& dbg = RS_DBG("returning: [");
|
||||||
std::cout << "getLocalAddresses(...) returning: <" ;
|
for(auto& addr: std::as_const(addrs))
|
||||||
for(it = addrs.begin(); it != addrs.end(); ++it)
|
dbg << sockaddr_storage_iptostring(addr) << ", ";
|
||||||
std::cout << sockaddr_storage_iptostring(*it) << ", ";
|
dbg << "]" << std::endl;
|
||||||
std::cout << ">" << std::endl;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return !addrs.empty();
|
return !addrs.empty();
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
* libretroshare: retroshare core library *
|
* libretroshare: retroshare core library *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2004-2006 Robert Fernie <retroshare@lunamutt.com> *
|
* Copyright (C) 2004-2006 Robert Fernie <retroshare@lunamutt.com> *
|
||||||
* Copyright (C) 2015-2018 Gioacchino Mazzurco <gio@eigenlab.org> *
|
* Copyright (C) 2015-2021 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
@ -20,8 +21,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
#ifndef MRK_PQI_NETWORKING_HEADER
|
#pragma once
|
||||||
#define MRK_PQI_NETWORKING_HEADER
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -86,9 +86,13 @@ extern int errno; /* Define extern errno, to duplicate unix behaviour */
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
|
#include "util/rsdeprecate.h"
|
||||||
|
|
||||||
// Same def - different functions...
|
// Same def - different functions...
|
||||||
|
RS_DEPRECATED_FOR("use std::error_condition instead")
|
||||||
void showSocketError(std::string &out);
|
void showSocketError(std::string &out);
|
||||||
|
|
||||||
|
RS_DEPRECATED_FOR("use std::error_condition instead")
|
||||||
std::string socket_errorType(int err);
|
std::string socket_errorType(int err);
|
||||||
|
|
||||||
bool getLocalAddresses(std::vector<sockaddr_storage> & addrs);
|
bool getLocalAddresses(std::vector<sockaddr_storage> & addrs);
|
||||||
|
@ -103,10 +107,6 @@ int unix_getsockopt_error(int sockfd, int *err);
|
||||||
|
|
||||||
#ifdef WINDOWS_SYS // WINDOWS
|
#ifdef WINDOWS_SYS // WINDOWS
|
||||||
/******************* WINDOWS SPECIFIC PART ******************/
|
/******************* WINDOWS SPECIFIC PART ******************/
|
||||||
|
RS_DEPRECATED_FOR("use std::error_condition instead")
|
||||||
int WinToUnixError(int error);
|
int WinToUnixError(int error);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
|
@ -1213,8 +1213,7 @@ int pqissl::Authorise_SSL_Connection()
|
||||||
}
|
}
|
||||||
|
|
||||||
RsPgpId pgpId = RsX509Cert::getCertIssuer(*peercert);
|
RsPgpId pgpId = RsX509Cert::getCertIssuer(*peercert);
|
||||||
if( !isSslOnlyFriend && pgpId != AuthGPG::getAuthGPG()->getGPGOwnId() &&
|
if( !isSslOnlyFriend && pgpId != AuthPGP::getPgpOwnId() && !AuthPGP::isPGPAccepted(pgpId) )
|
||||||
!AuthGPG::getAuthGPG()->isGPGAccepted(pgpId) )
|
|
||||||
{
|
{
|
||||||
RsFatal() << __PRETTY_FUNCTION__ << " pgpId: " << pgpId
|
RsFatal() << __PRETTY_FUNCTION__ << " pgpId: " << pgpId
|
||||||
<< " is not friend. It is very unlikely to happen at this "
|
<< " is not friend. It is very unlikely to happen at this "
|
||||||
|
|
|
@ -797,8 +797,7 @@ int pqissllistener::completeConnection(int fd, IncomingSSLInfo& info)
|
||||||
exit(failure);
|
exit(failure);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !isSslOnlyFriend && pgpId != AuthGPG::getAuthGPG()->getGPGOwnId() &&
|
if( !isSslOnlyFriend && pgpId != AuthPGP::getPgpOwnId() && !AuthPGP::isPGPAccepted(pgpId) )
|
||||||
!AuthGPG::getAuthGPG()->isGPGAccepted(pgpId) )
|
|
||||||
{
|
{
|
||||||
RsFatal() << __PRETTY_FUNCTION__ << " pgpId: " << pgpId
|
RsFatal() << __PRETTY_FUNCTION__ << " pgpId: " << pgpId
|
||||||
<< " is not friend. It is very unlikely to happen at this "
|
<< " is not friend. It is very unlikely to happen at this "
|
||||||
|
|
|
@ -450,6 +450,17 @@ public:
|
||||||
const std::string& matchString,
|
const std::string& matchString,
|
||||||
std::vector<RsGxsSearchResult>& searchResults ) = 0;
|
std::vector<RsGxsSearchResult>& searchResults ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Request Synchronization with available peers
|
||||||
|
* Usually syncronization already happen automatically so be carefull
|
||||||
|
* to call this method only if necessary.
|
||||||
|
* It has been thinked for use cases like mobile phone where internet
|
||||||
|
* connection is intermittent and calling this may be useful when a system
|
||||||
|
* event about connection being available or about to go offline is received
|
||||||
|
* @jsonapi{development}
|
||||||
|
* @return Success or error details
|
||||||
|
*/
|
||||||
|
virtual std::error_condition requestSynchronization() = 0;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
/* Following functions are deprecated and should not be considered a stable
|
/* Following functions are deprecated and should not be considered a stable
|
||||||
|
|
|
@ -887,7 +887,7 @@ public:
|
||||||
// Certificate utils
|
// Certificate utils
|
||||||
virtual bool cleanCertificate(
|
virtual bool cleanCertificate(
|
||||||
const std::string& certstr, std::string& cleanCert,
|
const std::string& certstr, std::string& cleanCert,
|
||||||
bool& is_short_format, uint32_t& error_code ) = 0;
|
bool& is_short_format, uint32_t& error_code, RsPeerDetails& details) = 0;
|
||||||
virtual std::string saveCertificateToString(const RsPeerId &id) = 0;
|
virtual std::string saveCertificateToString(const RsPeerId &id) = 0;
|
||||||
|
|
||||||
virtual bool signGPGCertificate(const RsPgpId &gpg_id,const std::string& gpg_passphrase) = 0;
|
virtual bool signGPGCertificate(const RsPgpId &gpg_id,const std::string& gpg_passphrase) = 0;
|
||||||
|
|
75
libretroshare/src/rs_android/LocalArray.h
Normal file
75
libretroshare/src/rs_android/LocalArray.h
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* 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 LOCAL_ARRAY_H_included
|
||||||
|
#define LOCAL_ARRAY_H_included
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A fixed-size array with a size hint. That number of bytes will be allocated
|
||||||
|
* on the stack, and used if possible, but if more bytes are requested at
|
||||||
|
* construction time, a buffer will be allocated on the heap (and deallocated
|
||||||
|
* by the destructor).
|
||||||
|
*
|
||||||
|
* The API is intended to be a compatible subset of C++0x's std::array.
|
||||||
|
*/
|
||||||
|
template <size_t STACK_BYTE_COUNT>
|
||||||
|
class LocalArray {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Allocates a new fixed-size array of the given size. If this size is
|
||||||
|
* less than or equal to the template parameter STACK_BYTE_COUNT, an
|
||||||
|
* internal on-stack buffer will be used. Otherwise a heap buffer will
|
||||||
|
* be allocated.
|
||||||
|
*/
|
||||||
|
LocalArray(size_t desiredByteCount) : mSize(desiredByteCount) {
|
||||||
|
if (desiredByteCount > STACK_BYTE_COUNT) {
|
||||||
|
mPtr = new char[mSize];
|
||||||
|
} else {
|
||||||
|
mPtr = &mOnStackBuffer[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frees the heap-allocated buffer, if there was one.
|
||||||
|
*/
|
||||||
|
~LocalArray() {
|
||||||
|
if (mPtr != &mOnStackBuffer[0]) {
|
||||||
|
delete[] mPtr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Capacity.
|
||||||
|
size_t size() { return mSize; }
|
||||||
|
bool empty() { return mSize == 0; }
|
||||||
|
|
||||||
|
// Element access.
|
||||||
|
char& operator[](size_t n) { return mPtr[n]; }
|
||||||
|
const char& operator[](size_t n) const { return mPtr[n]; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
char mOnStackBuffer[STACK_BYTE_COUNT];
|
||||||
|
char* mPtr;
|
||||||
|
size_t mSize;
|
||||||
|
|
||||||
|
// Disallow copy and assignment.
|
||||||
|
LocalArray(const LocalArray&);
|
||||||
|
void operator=(const LocalArray&);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LOCAL_ARRAY_H_included
|
49
libretroshare/src/rs_android/README-ifaddrs-android.adoc
Normal file
49
libretroshare/src/rs_android/README-ifaddrs-android.adoc
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
= README Android ifaddrs
|
||||||
|
|
||||||
|
Android API level < 24 doesn't provide `getifaddrs` and related functions, we
|
||||||
|
have tested multiple ways to overcome this issue.
|
||||||
|
|
||||||
|
|
||||||
|
== Non Weorking alternative implementations
|
||||||
|
|
||||||
|
https://github.com/kmackay/android-ifaddrs
|
||||||
|
https://github.com/morristech/android-ifaddrs
|
||||||
|
https://www.openhub.net/p/android-ifaddrs/
|
||||||
|
|
||||||
|
Compiles but then segfault at runtime.
|
||||||
|
|
||||||
|
|
||||||
|
== Qt implementation
|
||||||
|
|
||||||
|
Using `QNetworkInterface::allAddresses()` provided by Qt works but at time of
|
||||||
|
writing (Q4 2021) on newer Android the log is flooded by warnings as we reported
|
||||||
|
here
|
||||||
|
https://bugreports.qt.io/browse/QTBUG-78659
|
||||||
|
plus depending on Qt networking module just for this is frustrating.
|
||||||
|
|
||||||
|
Update: the warning flood seems have been fixed in later Qt versions
|
||||||
|
https://bugreports.qt.io/browse/QTBUG-86394
|
||||||
|
|
||||||
|
This solution was the first working we implemented in our code it has been
|
||||||
|
removed to avoid dependency on Qt, as lighter alternatives are possible.
|
||||||
|
|
||||||
|
|
||||||
|
== Code copied from Android Gingerbread release
|
||||||
|
|
||||||
|
As explained here
|
||||||
|
https://stackoverflow.com/a/57112520
|
||||||
|
|
||||||
|
even older Android have `getifaddrs` implementations but doesn't make them
|
||||||
|
accessible in the API, in particular the one included in Android Gingerbread
|
||||||
|
|
||||||
|
https://android.googlesource.com/platform/libcore/+/refs/heads/gingerbread-release/luni/src/main/native/ifaddrs-android.h
|
||||||
|
https://android.googlesource.com/platform/libcore/+/refs/heads/gingerbread-release/
|
||||||
|
|
||||||
|
is particularly easy to include in our code base and compile.
|
||||||
|
|
||||||
|
This solution seems the best fitting and doesn't introduce dependency on Qt.
|
||||||
|
Newer Android releases (expecially 11) have introduced multiple restrictions
|
||||||
|
on network information access so we suggest you to prepare different APK for
|
||||||
|
different API level in order to use the `getifaddrs` provided by Android NDK
|
||||||
|
which deal gracefully with those restrictions as soon as available.
|
||||||
|
|
46
libretroshare/src/rs_android/ScopedFd.h
Normal file
46
libretroshare/src/rs_android/ScopedFd.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* 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 SCOPED_FD_H_included
|
||||||
|
#define SCOPED_FD_H_included
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
// A smart pointer that closes the given fd on going out of scope.
|
||||||
|
// Use this when the fd is incidental to the purpose of your function,
|
||||||
|
// but needs to be cleaned up on exit.
|
||||||
|
class ScopedFd {
|
||||||
|
public:
|
||||||
|
explicit ScopedFd(int fd) : fd(fd) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~ScopedFd() {
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int get() const {
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
// Disallow copy and assignment.
|
||||||
|
ScopedFd(const ScopedFd&);
|
||||||
|
void operator=(const ScopedFd&);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SCOPED_FD_H_included
|
|
@ -1,9 +1,9 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* libretroshare/src/util: androiddebug.h *
|
|
||||||
* *
|
* *
|
||||||
* libretroshare: retroshare core library *
|
* libretroshare: retroshare core library *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2016 Gioacchino Mazzurco <gio@eigenlab.org> *
|
* Copyright (C) 2016-2021 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
@ -36,10 +36,10 @@
|
||||||
* class at the beginning of the main of your program to get them (stdout and
|
* class at the beginning of the main of your program to get them (stdout and
|
||||||
* stderr) on logcat output.
|
* stderr) on logcat output.
|
||||||
*/
|
*/
|
||||||
class AndroidStdIOCatcher
|
class AndroidCoutCerrCatcher
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AndroidStdIOCatcher(const std::string& dTag = "RetroShare",
|
AndroidCoutCerrCatcher(const std::string& dTag = "RetroShare",
|
||||||
android_LogPriority stdout_pri = ANDROID_LOG_INFO,
|
android_LogPriority stdout_pri = ANDROID_LOG_INFO,
|
||||||
android_LogPriority stderr_pri = ANDROID_LOG_ERROR) :
|
android_LogPriority stderr_pri = ANDROID_LOG_ERROR) :
|
||||||
tag(dTag), cout_pri(stdout_pri), cerr_pri(stderr_pri), should_stop(false)
|
tag(dTag), cout_pri(stdout_pri), cerr_pri(stderr_pri), should_stop(false)
|
||||||
|
@ -63,10 +63,10 @@ public:
|
||||||
pthread_detach(thr);
|
pthread_detach(thr);
|
||||||
}
|
}
|
||||||
|
|
||||||
~AndroidStdIOCatcher()
|
~AndroidCoutCerrCatcher()
|
||||||
{
|
{
|
||||||
should_stop = true;
|
should_stop = true;
|
||||||
pthread_join(thr, NULL);
|
pthread_join(thr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -79,11 +79,13 @@ private:
|
||||||
pthread_t thr;
|
pthread_t thr;
|
||||||
std::atomic<bool> should_stop;
|
std::atomic<bool> should_stop;
|
||||||
|
|
||||||
static void *thread_func(void* instance)
|
static void* thread_func(void* instance)
|
||||||
{
|
{
|
||||||
__android_log_write(ANDROID_LOG_INFO, "RetroShare", "Android debugging start");
|
__android_log_write(
|
||||||
|
ANDROID_LOG_INFO, "RetroShare",
|
||||||
|
"Android standard I/O catcher start" );
|
||||||
|
|
||||||
AndroidStdIOCatcher &i = *static_cast<AndroidStdIOCatcher*>(instance);
|
AndroidCoutCerrCatcher &i = *static_cast<AndroidCoutCerrCatcher*>(instance);
|
||||||
|
|
||||||
std::string out_buf;
|
std::string out_buf;
|
||||||
std::string err_buf;
|
std::string err_buf;
|
||||||
|
@ -113,9 +115,11 @@ private:
|
||||||
usleep(10000);
|
usleep(10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
__android_log_write(ANDROID_LOG_INFO, "RetroShare", "Android debugging stop");
|
__android_log_write(
|
||||||
|
ANDROID_LOG_INFO, "RetroShare",
|
||||||
|
"Android standard I/O catcher stop" );
|
||||||
|
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
42
libretroshare/src/rs_android/errorconditionwrap.cpp
Normal file
42
libretroshare/src/rs_android/errorconditionwrap.cpp
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* *
|
||||||
|
* libretroshare: retroshare core library *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2021 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.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 <https://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include "rs_android/rsjni.hpp"
|
||||||
|
|
||||||
|
namespace jni
|
||||||
|
{
|
||||||
|
Local<Object<RsJni::ErrorConditionWrap>> MakeAnything(
|
||||||
|
ThingToMake<RsJni::ErrorConditionWrap>, JNIEnv& env,
|
||||||
|
const std::error_condition& ec )
|
||||||
|
{
|
||||||
|
auto& clazz = jni::Class<RsJni::ErrorConditionWrap>::Singleton(env);
|
||||||
|
|
||||||
|
static auto method =
|
||||||
|
clazz.GetConstructor<jni::jint, jni::String, jni::String>(env);
|
||||||
|
|
||||||
|
jni::jint value = ec.value();
|
||||||
|
auto message = jni::Make<jni::String>(env, ec.message());
|
||||||
|
auto category = jni::Make<jni::String>(env, ec.category().name());
|
||||||
|
|
||||||
|
return clazz.New(env, method, value, message, category);
|
||||||
|
}
|
||||||
|
}
|
228
libretroshare/src/rs_android/ifaddrs-android.h
Normal file
228
libretroshare/src/rs_android/ifaddrs-android.h
Normal file
|
@ -0,0 +1,228 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* 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 IFADDRS_ANDROID_H_included
|
||||||
|
#define IFADDRS_ANDROID_H_included
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <new>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <linux/netlink.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
|
||||||
|
#include "LocalArray.h"
|
||||||
|
#include "ScopedFd.h"
|
||||||
|
|
||||||
|
// Android (bionic) doesn't have getifaddrs(3)/freeifaddrs(3).
|
||||||
|
// We fake it here, so java_net_NetworkInterface.cpp can use that API
|
||||||
|
// with all the non-portable code being in this file.
|
||||||
|
|
||||||
|
// Source-compatible subset of the BSD struct.
|
||||||
|
struct ifaddrs {
|
||||||
|
// Pointer to next struct in list, or NULL at end.
|
||||||
|
ifaddrs* ifa_next;
|
||||||
|
|
||||||
|
// Interface name.
|
||||||
|
char* ifa_name;
|
||||||
|
|
||||||
|
// Interface flags.
|
||||||
|
unsigned int ifa_flags;
|
||||||
|
|
||||||
|
// Interface network address.
|
||||||
|
sockaddr* ifa_addr;
|
||||||
|
|
||||||
|
// Interface netmask.
|
||||||
|
sockaddr* ifa_netmask;
|
||||||
|
|
||||||
|
ifaddrs(ifaddrs* next)
|
||||||
|
: ifa_next(next), ifa_name(NULL), ifa_flags(0), ifa_addr(NULL), ifa_netmask(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~ifaddrs() {
|
||||||
|
delete ifa_next;
|
||||||
|
delete[] ifa_name;
|
||||||
|
delete ifa_addr;
|
||||||
|
delete ifa_netmask;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sadly, we can't keep the interface index for portability with BSD.
|
||||||
|
// We'll have to keep the name instead, and re-query the index when
|
||||||
|
// we need it later.
|
||||||
|
bool setNameAndFlagsByIndex(int interfaceIndex) {
|
||||||
|
// Get the name.
|
||||||
|
char buf[IFNAMSIZ];
|
||||||
|
char* name = if_indextoname(interfaceIndex, buf);
|
||||||
|
if (name == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ifa_name = new char[strlen(name) + 1];
|
||||||
|
strcpy(ifa_name, name);
|
||||||
|
|
||||||
|
// Get the flags.
|
||||||
|
ScopedFd fd(socket(AF_INET, SOCK_DGRAM, 0));
|
||||||
|
if (fd.get() == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ifreq ifr;
|
||||||
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
|
strcpy(ifr.ifr_name, name);
|
||||||
|
int rc = ioctl(fd.get(), SIOCGIFFLAGS, &ifr);
|
||||||
|
if (rc == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ifa_flags = ifr.ifr_flags;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Netlink gives us the address family in the header, and the
|
||||||
|
// sockaddr_in or sockaddr_in6 bytes as the payload. We need to
|
||||||
|
// stitch the two bits together into the sockaddr that's part of
|
||||||
|
// our portable interface.
|
||||||
|
void setAddress(int family, void* data, size_t byteCount) {
|
||||||
|
// Set the address proper...
|
||||||
|
sockaddr_storage* ss = new sockaddr_storage;
|
||||||
|
memset(ss, 0, sizeof(*ss));
|
||||||
|
ifa_addr = reinterpret_cast<sockaddr*>(ss);
|
||||||
|
ss->ss_family = family;
|
||||||
|
uint8_t* dst = sockaddrBytes(family, ss);
|
||||||
|
memcpy(dst, data, byteCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Netlink gives us the prefix length as a bit count. We need to turn
|
||||||
|
// that into a BSD-compatible netmask represented by a sockaddr*.
|
||||||
|
void setNetmask(int family, size_t prefixLength) {
|
||||||
|
// ...and work out the netmask from the prefix length.
|
||||||
|
sockaddr_storage* ss = new sockaddr_storage;
|
||||||
|
memset(ss, 0, sizeof(*ss));
|
||||||
|
ifa_netmask = reinterpret_cast<sockaddr*>(ss);
|
||||||
|
ss->ss_family = family;
|
||||||
|
uint8_t* dst = sockaddrBytes(family, ss);
|
||||||
|
memset(dst, 0xff, prefixLength / 8);
|
||||||
|
if ((prefixLength % 8) != 0) {
|
||||||
|
dst[prefixLength/8] = (0xff << (8 - (prefixLength % 8)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a pointer to the first byte in the address data (which is
|
||||||
|
// stored in network byte order).
|
||||||
|
uint8_t* sockaddrBytes(int family, sockaddr_storage* ss) {
|
||||||
|
if (family == AF_INET) {
|
||||||
|
sockaddr_in* ss4 = reinterpret_cast<sockaddr_in*>(ss);
|
||||||
|
return reinterpret_cast<uint8_t*>(&ss4->sin_addr);
|
||||||
|
} else if (family == AF_INET6) {
|
||||||
|
sockaddr_in6* ss6 = reinterpret_cast<sockaddr_in6*>(ss);
|
||||||
|
return reinterpret_cast<uint8_t*>(&ss6->sin6_addr);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Disallow copy and assignment.
|
||||||
|
ifaddrs(const ifaddrs&);
|
||||||
|
void operator=(const ifaddrs&);
|
||||||
|
};
|
||||||
|
|
||||||
|
// FIXME: use iovec instead.
|
||||||
|
struct addrReq_struct {
|
||||||
|
nlmsghdr netlinkHeader;
|
||||||
|
ifaddrmsg msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool sendNetlinkMessage(int fd, const void* data, size_t byteCount) {
|
||||||
|
ssize_t sentByteCount = TEMP_FAILURE_RETRY(send(fd, data, byteCount, 0));
|
||||||
|
return (sentByteCount == static_cast<ssize_t>(byteCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ssize_t recvNetlinkMessage(int fd, char* buf, size_t byteCount) {
|
||||||
|
return TEMP_FAILURE_RETRY(recv(fd, buf, byteCount, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source-compatible with the BSD function.
|
||||||
|
inline int getifaddrs(ifaddrs** result) {
|
||||||
|
// Simplify cleanup for callers.
|
||||||
|
*result = NULL;
|
||||||
|
|
||||||
|
// Create a netlink socket.
|
||||||
|
ScopedFd fd(socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE));
|
||||||
|
if (fd.get() < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ask for the address information.
|
||||||
|
addrReq_struct addrRequest;
|
||||||
|
memset(&addrRequest, 0, sizeof(addrRequest));
|
||||||
|
addrRequest.netlinkHeader.nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH;
|
||||||
|
addrRequest.netlinkHeader.nlmsg_type = RTM_GETADDR;
|
||||||
|
addrRequest.netlinkHeader.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(addrRequest)));
|
||||||
|
addrRequest.msg.ifa_family = AF_UNSPEC; // All families.
|
||||||
|
addrRequest.msg.ifa_index = 0; // All interfaces.
|
||||||
|
if (!sendNetlinkMessage(fd.get(), &addrRequest, addrRequest.netlinkHeader.nlmsg_len)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the responses.
|
||||||
|
LocalArray<0> buf(65536); // We don't necessarily have std::vector.
|
||||||
|
ssize_t bytesRead;
|
||||||
|
while ((bytesRead = recvNetlinkMessage(fd.get(), &buf[0], buf.size())) > 0) {
|
||||||
|
nlmsghdr* hdr = reinterpret_cast<nlmsghdr*>(&buf[0]);
|
||||||
|
for (; NLMSG_OK(hdr, (size_t)bytesRead); hdr = NLMSG_NEXT(hdr, bytesRead)) {
|
||||||
|
switch (hdr->nlmsg_type) {
|
||||||
|
case NLMSG_DONE:
|
||||||
|
return 0;
|
||||||
|
case NLMSG_ERROR:
|
||||||
|
return -1;
|
||||||
|
case RTM_NEWADDR:
|
||||||
|
{
|
||||||
|
ifaddrmsg* address = reinterpret_cast<ifaddrmsg*>(NLMSG_DATA(hdr));
|
||||||
|
rtattr* rta = IFA_RTA(address);
|
||||||
|
size_t ifaPayloadLength = IFA_PAYLOAD(hdr);
|
||||||
|
while (RTA_OK(rta, ifaPayloadLength)) {
|
||||||
|
if (rta->rta_type == IFA_LOCAL) {
|
||||||
|
int family = address->ifa_family;
|
||||||
|
if (family == AF_INET || family == AF_INET6) {
|
||||||
|
*result = new ifaddrs(*result);
|
||||||
|
if (!(*result)->setNameAndFlagsByIndex(address->ifa_index)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
(*result)->setAddress(family, RTA_DATA(rta), RTA_PAYLOAD(rta));
|
||||||
|
(*result)->setNetmask(family, address->ifa_prefixlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rta = RTA_NEXT(rta, ifaPayloadLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// We only get here if recv fails before we see a NLMSG_DONE.
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source-compatible with the BSD function.
|
||||||
|
inline void freeifaddrs(ifaddrs* addresses) {
|
||||||
|
delete addresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // IFADDRS_ANDROID_H_included
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
* RetroShare
|
||||||
|
* Copyright (C) 2021 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: Retroshare Team <contact@retroshare.cc>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.retroshare.service;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
import android.content.Context;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
|
||||||
|
public class AssetHelper
|
||||||
|
{
|
||||||
|
public static boolean copyAsset(
|
||||||
|
Context ctx, String assetPath, String destinationFilePath )
|
||||||
|
{
|
||||||
|
Log.d(TAG, "copyAsset " + assetPath + " -> " + destinationFilePath);
|
||||||
|
|
||||||
|
InputStream in;
|
||||||
|
OutputStream out;
|
||||||
|
|
||||||
|
try { in = ctx.getAssets().open(assetPath); }
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
Log.e(
|
||||||
|
TAG,
|
||||||
|
"Failure opening asset: " + assetPath + " " + e.getMessage() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try { out = new FileOutputStream(destinationFilePath); }
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
Log.e(
|
||||||
|
TAG,
|
||||||
|
"Failure opening destination: " + destinationFilePath + " " +
|
||||||
|
e.getMessage() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte[] buf = new byte[1024];
|
||||||
|
int len;
|
||||||
|
while ((len = in.read(buf)) > 0) out.write(buf, 0, len);
|
||||||
|
}
|
||||||
|
catch(IOException e)
|
||||||
|
{
|
||||||
|
Log.e(
|
||||||
|
TAG,
|
||||||
|
"Failure coping: " + assetPath + " -> " + destinationFilePath +
|
||||||
|
" " + e.getMessage() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try { in.close(); }
|
||||||
|
catch(IOException e)
|
||||||
|
{
|
||||||
|
Log.e(TAG, "Failure closing: " + assetPath + " " + e.getMessage() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try { out.close(); }
|
||||||
|
catch(IOException e)
|
||||||
|
{
|
||||||
|
Log.e(
|
||||||
|
TAG,
|
||||||
|
"Failure closing: " + destinationFilePath + " " +
|
||||||
|
e.getMessage() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String TAG = "RetroShare AssetHelper.java";
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* RetroShare
|
||||||
|
* Copyright (C) 2021 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: Retroshare Team <contact@retroshare.cc>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.retroshare.service;
|
||||||
|
|
||||||
|
public class ErrorConditionWrap
|
||||||
|
{
|
||||||
|
public ErrorConditionWrap(
|
||||||
|
int value, String message, String categoryName )
|
||||||
|
{
|
||||||
|
mValue = value;
|
||||||
|
mMessage = message;
|
||||||
|
mCategoryName = categoryName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int value() { return mValue; }
|
||||||
|
public String message() { return mMessage; }
|
||||||
|
public String categoryName() { return mCategoryName; }
|
||||||
|
|
||||||
|
public boolean toBool() { return mValue != 0; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{ return String.format("%d", mValue)+" "+mMessage+" [" + mCategoryName+ "]"; }
|
||||||
|
|
||||||
|
private int mValue = 0;
|
||||||
|
private String mMessage;
|
||||||
|
private String mCategoryName;
|
||||||
|
}
|
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
* RetroShare
|
||||||
|
* Copyright (C) 2016-2021 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: Retroshare Team <contact@retroshare.cc>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.retroshare.service;
|
||||||
|
|
||||||
|
import android.app.Service;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.app.ActivityManager;
|
||||||
|
|
||||||
|
|
||||||
|
public class RetroShareServiceAndroid extends Service
|
||||||
|
{
|
||||||
|
public static final int DEFAULT_JSON_API_PORT = 9092;
|
||||||
|
public static final String DEFAULT_JSON_API_BINDING_ADDRESS = "127.0.0.1";
|
||||||
|
|
||||||
|
static { System.loadLibrary("retroshare-service"); }
|
||||||
|
|
||||||
|
public static void start(
|
||||||
|
Context ctx, int jsonApiPort, String jsonApiBindAddress )
|
||||||
|
{
|
||||||
|
Log.d(TAG, "start");
|
||||||
|
Intent intent = new Intent(ctx, RetroShareServiceAndroid.class);
|
||||||
|
intent.putExtra(JSON_API_PORT_KEY, jsonApiPort);
|
||||||
|
intent.putExtra(JSON_API_BIND_ADDRESS_KEY, jsonApiBindAddress);
|
||||||
|
ctx.startService(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void stop(Context ctx)
|
||||||
|
{
|
||||||
|
Log.d(TAG, "stop");
|
||||||
|
ctx.stopService(new Intent(ctx, RetroShareServiceAndroid.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isRunning(Context ctx)
|
||||||
|
{
|
||||||
|
Log.d(TAG, "isRunning");
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Context getServiceContext()
|
||||||
|
{
|
||||||
|
if(sServiceContext == null)
|
||||||
|
{
|
||||||
|
Log.e(TAG, "getServiceContext() called before onCreate");
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
return sServiceContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int onStartCommand(
|
||||||
|
Intent intent, int flags, int startId )
|
||||||
|
{
|
||||||
|
if(intent == null)
|
||||||
|
{
|
||||||
|
Log.i(TAG, "onStartCommand called without intent");
|
||||||
|
return Service.START_REDELIVER_INTENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int jsonApiPort = DEFAULT_JSON_API_PORT;
|
||||||
|
String jsonApiBindAddress = DEFAULT_JSON_API_BINDING_ADDRESS;
|
||||||
|
|
||||||
|
Bundle args = intent.getExtras();
|
||||||
|
if(args.containsKey(JSON_API_PORT_KEY))
|
||||||
|
jsonApiPort = args.getInt(JSON_API_PORT_KEY);
|
||||||
|
if(args.containsKey(JSON_API_BIND_ADDRESS_KEY))
|
||||||
|
jsonApiBindAddress =
|
||||||
|
args.getString(JSON_API_BIND_ADDRESS_KEY);
|
||||||
|
|
||||||
|
ErrorConditionWrap ec = nativeStart(jsonApiPort, jsonApiBindAddress);
|
||||||
|
if(ec.toBool()) Log.e(TAG, "onStartCommand(...) " + ec.toString());
|
||||||
|
|
||||||
|
return super.onStartCommand(intent, flags, startId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate ()
|
||||||
|
{
|
||||||
|
super.onCreate();
|
||||||
|
sServiceContext = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy()
|
||||||
|
{
|
||||||
|
ErrorConditionWrap ec = nativeStop();
|
||||||
|
if(ec.toBool()) Log.e(TAG, "onDestroy() " + ec.toString());
|
||||||
|
sServiceContext = null;
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent arg0) { return null; }
|
||||||
|
|
||||||
|
private static final String JSON_API_PORT_KEY =
|
||||||
|
RetroShareServiceAndroid.class.getCanonicalName() +
|
||||||
|
"/JSON_API_PORT_KEY";
|
||||||
|
|
||||||
|
private static final String JSON_API_BIND_ADDRESS_KEY =
|
||||||
|
RetroShareServiceAndroid.class.getCanonicalName() +
|
||||||
|
"/JSON_API_BIND_ADDRESS_KEY" ;
|
||||||
|
|
||||||
|
private static final String TAG = "RetroShareServiceAndroid.java";
|
||||||
|
|
||||||
|
private static Context sServiceContext;
|
||||||
|
|
||||||
|
protected static native ErrorConditionWrap nativeStart(
|
||||||
|
int jsonApiPort, String jsonApiBindAddress );
|
||||||
|
|
||||||
|
protected static native ErrorConditionWrap nativeStop();
|
||||||
|
}
|
103
libretroshare/src/rs_android/retroshareserviceandroid.cpp
Normal file
103
libretroshare/src/rs_android/retroshareserviceandroid.cpp
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
* RetroShare Service Android
|
||||||
|
* Copyright (C) 2016-2021 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: Retroshare Team <contact@retroshare.cc>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "util/stacktrace.h"
|
||||||
|
#include "retroshare/rsinit.h"
|
||||||
|
#include "retroshare/rsiface.h"
|
||||||
|
#include "util/rsdebug.h"
|
||||||
|
|
||||||
|
#include "rs_android/retroshareserviceandroid.hpp"
|
||||||
|
#include "rs_android/rsjni.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ std::unique_ptr<AndroidCoutCerrCatcher>
|
||||||
|
RetroShareServiceAndroid::sAndroidCoutCerrCatcher = nullptr;
|
||||||
|
|
||||||
|
using ErrorConditionWrap = RsJni::ErrorConditionWrap;
|
||||||
|
|
||||||
|
/*static*/ jni::Local<jni::Object<ErrorConditionWrap>>
|
||||||
|
RetroShareServiceAndroid::start(
|
||||||
|
JNIEnv& env, jni::Class<RetroShareServiceAndroid>&,
|
||||||
|
jni::jint jsonApiPort, const jni::String& jsonApiBindAddress )
|
||||||
|
{
|
||||||
|
if(jsonApiPort < 0 || jsonApiPort > std::numeric_limits<uint16_t>::max())
|
||||||
|
{
|
||||||
|
RS_ERR("Got invalid JSON API port: ", jsonApiPort);
|
||||||
|
return jni::Make<ErrorConditionWrap>(env, std::errc::invalid_argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
RsInfo() << "\n" <<
|
||||||
|
"+================================================================+\n"
|
||||||
|
"| o---o o |\n"
|
||||||
|
"| \\ / - Retroshare Service Android - / \\ |\n"
|
||||||
|
"| o o---o |\n"
|
||||||
|
"+================================================================+"
|
||||||
|
<< std::endl << std::endl;
|
||||||
|
|
||||||
|
sAndroidCoutCerrCatcher = std::make_unique<AndroidCoutCerrCatcher>();
|
||||||
|
|
||||||
|
RsInit::InitRsConfig();
|
||||||
|
RsControl::earlyInitNotificationSystem();
|
||||||
|
|
||||||
|
RsConfigOptions conf;
|
||||||
|
conf.jsonApiPort = static_cast<uint16_t>(jsonApiPort);
|
||||||
|
conf.jsonApiBindAddress = jni::Make<std::string>(env, jsonApiBindAddress);
|
||||||
|
|
||||||
|
// Dirty workaround plugins not supported on Android ATM
|
||||||
|
conf.main_executable_path = " ";
|
||||||
|
|
||||||
|
int initResult = RsInit::InitRetroShare(conf);
|
||||||
|
if(initResult != RS_INIT_OK)
|
||||||
|
{
|
||||||
|
RS_ERR("Retroshare core initalization failed with: ", initResult);
|
||||||
|
return jni::Make<ErrorConditionWrap>(env, std::errc::no_child_process);
|
||||||
|
}
|
||||||
|
|
||||||
|
return jni::Make<ErrorConditionWrap>(env, std::error_condition());
|
||||||
|
}
|
||||||
|
|
||||||
|
jni::Local<jni::Object<ErrorConditionWrap>> RetroShareServiceAndroid::stop(
|
||||||
|
JNIEnv& env, jni::Class<RetroShareServiceAndroid>& )
|
||||||
|
{
|
||||||
|
if(RsControl::instance()->isReady())
|
||||||
|
{
|
||||||
|
RsControl::instance()->rsGlobalShutDown();
|
||||||
|
return jni::Make<ErrorConditionWrap>(env, std::error_condition());
|
||||||
|
}
|
||||||
|
|
||||||
|
sAndroidCoutCerrCatcher.reset();
|
||||||
|
|
||||||
|
return jni::Make<ErrorConditionWrap>(env, std::errc::no_such_process);
|
||||||
|
}
|
||||||
|
|
||||||
|
jni::Local<jni::Object<RetroShareServiceAndroid::Context> >
|
||||||
|
RetroShareServiceAndroid::getAndroidContext(JNIEnv& env)
|
||||||
|
{
|
||||||
|
auto& clazz = jni::Class<RetroShareServiceAndroid>::Singleton(env);
|
||||||
|
static auto method =
|
||||||
|
clazz.GetStaticMethod<jni::Object<RetroShareServiceAndroid::Context>()>(
|
||||||
|
env, "getServiceContext" );
|
||||||
|
return clazz.Call(env, method);
|
||||||
|
}
|
84
libretroshare/src/rs_android/retroshareserviceandroid.hpp
Normal file
84
libretroshare/src/rs_android/retroshareserviceandroid.hpp
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* RetroShare Service Android
|
||||||
|
* Copyright (C) 2016-2021 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: Retroshare Team <contact@retroshare.cc>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <system_error>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <jni/jni.hpp>
|
||||||
|
|
||||||
|
#include "rs_android/rsjni.hpp"
|
||||||
|
#include "rs_android/androidcoutcerrcatcher.hpp"
|
||||||
|
|
||||||
|
#include "util/stacktrace.h"
|
||||||
|
|
||||||
|
/** Provide native methods that are registered into corresponding Java class
|
||||||
|
* to start/stop RetroShare with reasonable comfort on Android platform */
|
||||||
|
struct RetroShareServiceAndroid
|
||||||
|
{
|
||||||
|
static constexpr auto Name()
|
||||||
|
{ return "org/retroshare/service/RetroShareServiceAndroid"; }
|
||||||
|
|
||||||
|
using ErrorConditionWrap = RsJni::ErrorConditionWrap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called from RetroShareServiceAndroid Java to init libretroshare
|
||||||
|
* @param[in] env the usual JNI parafernalia
|
||||||
|
* @param[in] jclass the usual JNI parafernalia
|
||||||
|
* @param[in] jsonApiPort port on which JSON API server will listen
|
||||||
|
* @param[in] jsonApiBindAddress binding address of the JSON API server
|
||||||
|
* @note Yeah you read it well we use a full 32 bit signed integer for JSON
|
||||||
|
* API port. This is because Java lack even the minimum decency to implement
|
||||||
|
* unsigned integral types so we need to wrap the port (16 bit unsigned
|
||||||
|
* integer everywhere reasonable) into a full integer and then check at
|
||||||
|
* runtime the value.
|
||||||
|
*/
|
||||||
|
static jni::Local<jni::Object<ErrorConditionWrap>> start(
|
||||||
|
JNIEnv& env, jni::Class<RetroShareServiceAndroid>& jclass,
|
||||||
|
jni::jint jsonApiPort, const jni::String& jsonApiBindAddress );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called from RetroShareServiceAndroid Java to shutdown libretroshare
|
||||||
|
* @param[in] env the usual JNI parafernalia
|
||||||
|
* @param[in] jclass the usual JNI parafernalia
|
||||||
|
*/
|
||||||
|
static jni::Local<jni::Object<ErrorConditionWrap>> stop(
|
||||||
|
JNIEnv& env, jni::Class<RetroShareServiceAndroid>& );
|
||||||
|
|
||||||
|
struct Context
|
||||||
|
{
|
||||||
|
/// JNI parafernalia
|
||||||
|
static constexpr auto Name() { return "android/content/Context"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Return RetroShare Service Android Context
|
||||||
|
static jni::Local<jni::Object<Context>> getAndroidContext(JNIEnv& env);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** Doesn't involve complex liftime handling stuff better let the runtime
|
||||||
|
* handle costruction (ASAP)/destruction for us */
|
||||||
|
static CrashStackTrace CrashStackTrace;
|
||||||
|
|
||||||
|
/** Involve threads, file descriptors etc. better handle lifetime
|
||||||
|
* explicitely */
|
||||||
|
static std::unique_ptr<AndroidCoutCerrCatcher> sAndroidCoutCerrCatcher;
|
||||||
|
};
|
70
libretroshare/src/rs_android/rsjni.cpp
Normal file
70
libretroshare/src/rs_android/rsjni.cpp
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* RetroShare JNI utilities *
|
||||||
|
* *
|
||||||
|
* libretroshare: retroshare core library *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2021 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.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 <https://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include "rs_android/rsjni.hpp"
|
||||||
|
#include "rs_android/retroshareserviceandroid.hpp"
|
||||||
|
|
||||||
|
rs_view_ptr<JavaVM> RsJni::mJvm = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jint JNICALL JNI_OnLoad_retroshare(JavaVM* vm, void*)
|
||||||
|
{
|
||||||
|
RS_DBG(vm);
|
||||||
|
|
||||||
|
RsJni::mJvm = vm;
|
||||||
|
|
||||||
|
jni::JNIEnv& env { jni::GetEnv(*vm) };
|
||||||
|
|
||||||
|
/** Ensure singleton refereces to our own Java classes are inizialized here
|
||||||
|
* because default Java class loader which is the one accessible by native
|
||||||
|
* threads which is not main even if attached, is not capable to find them.
|
||||||
|
* https://stackoverflow.com/questions/20752352/classnotfoundexception-when-finding-a-class-in-jni-background-thread
|
||||||
|
* https://groups.google.com/g/android-ndk/c/2gkr1mXKn_E */
|
||||||
|
jni::Class<RsJni::AssetHelper>::Singleton(env);
|
||||||
|
jni::Class<RsJni::ErrorConditionWrap>::Singleton(env);
|
||||||
|
|
||||||
|
jni::RegisterNatives(
|
||||||
|
env, *jni::Class<RetroShareServiceAndroid>::Singleton(env),
|
||||||
|
jni::MakeNativeMethod<
|
||||||
|
decltype(&RetroShareServiceAndroid::start),
|
||||||
|
&RetroShareServiceAndroid::start >("nativeStart"),
|
||||||
|
jni::MakeNativeMethod<
|
||||||
|
decltype(&RetroShareServiceAndroid::stop),
|
||||||
|
&RetroShareServiceAndroid::stop >("nativeStop")
|
||||||
|
);
|
||||||
|
|
||||||
|
return jni::Unwrap(jni::jni_version_1_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef RS_LIBRETROSHARE_EXPORT_JNI_ONLOAD
|
||||||
|
/** If libretroshare is linked statically to other components which already
|
||||||
|
* export JNI_OnLoad then a symbol clash may happen
|
||||||
|
* if RS_LIBRETROSHARE_EXPORT_JNI_ONLOAD is defined.
|
||||||
|
* @see JNI_OnLoad_retroshare should instead be called from the exported
|
||||||
|
* JNI_OnLoad */
|
||||||
|
extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* _reserved)
|
||||||
|
{
|
||||||
|
RS_DBG(vm);
|
||||||
|
return JNI_OnLoad_retroshare(vm, _reserved);
|
||||||
|
}
|
||||||
|
#endif // def RS_LIBRETROSHARE_EXPORT_JNI_ONLOAD
|
90
libretroshare/src/rs_android/rsjni.hpp
Normal file
90
libretroshare/src/rs_android/rsjni.hpp
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* RetroShare JNI utilities *
|
||||||
|
* *
|
||||||
|
* libretroshare: retroshare core library *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2021 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.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 <https://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
*******************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <system_error>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include <jni/jni.hpp>
|
||||||
|
|
||||||
|
#include "util/rsmemory.h"
|
||||||
|
#include "util/cxx23retrocompat.h"
|
||||||
|
|
||||||
|
|
||||||
|
/** Store JVM pointer safely and register native methods */
|
||||||
|
extern "C" JNIEXPORT jint JNICALL JNI_OnLoad_retroshare(JavaVM* vm, void*);
|
||||||
|
|
||||||
|
|
||||||
|
/** Provide library wide JVM access with some safe measures
|
||||||
|
* The JVM pointer is set properly by @see JNI_OnLoad_retroshare
|
||||||
|
*/
|
||||||
|
class RsJni
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static inline JavaVM& getVM()
|
||||||
|
{
|
||||||
|
if(!mJvm) // [[unlikely]]
|
||||||
|
{
|
||||||
|
RS_FATAL( "Attempt to access JVM before JNI_OnLoad_retroshare ",
|
||||||
|
std::errc::bad_address );
|
||||||
|
print_stacktrace();
|
||||||
|
std::exit(std::to_underlying(std::errc::bad_address));
|
||||||
|
}
|
||||||
|
|
||||||
|
return *mJvm;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend jint JNI_OnLoad_retroshare(JavaVM* vm, void*);
|
||||||
|
|
||||||
|
/** Provide a comfortable way to access Android package assets like
|
||||||
|
* bdboot.txt from C++ */
|
||||||
|
struct AssetHelper
|
||||||
|
{
|
||||||
|
static constexpr auto Name()
|
||||||
|
{ return "org/retroshare/service/AssetHelper"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Provide a comfortable way to propagate C++ error_conditions to Java
|
||||||
|
* callers */
|
||||||
|
struct ErrorConditionWrap
|
||||||
|
{
|
||||||
|
static constexpr auto Name()
|
||||||
|
{ return "org/retroshare/service/ErrorConditionWrap"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
static rs_view_ptr<JavaVM> mJvm;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
namespace jni
|
||||||
|
{
|
||||||
|
/** Provides idiomatic way of creating instances via
|
||||||
|
@code{.cpp}
|
||||||
|
jni::Make<ErrorConditionWrap>(env, std::error_condition());
|
||||||
|
@endcode */
|
||||||
|
jni::Local<jni::Object<RsJni::ErrorConditionWrap>>
|
||||||
|
MakeAnything(
|
||||||
|
jni::ThingToMake<RsJni::ErrorConditionWrap>, JNIEnv& env,
|
||||||
|
const std::error_condition& ec );
|
||||||
|
}
|
|
@ -3,7 +3,9 @@
|
||||||
* *
|
* *
|
||||||
* libretroshare: retroshare core library *
|
* libretroshare: retroshare core library *
|
||||||
* *
|
* *
|
||||||
* Copyright 2011-2011 by Cyril Soler <csoler@users.sourceforge.net> *
|
* Copyright (C) 2011-2018 Cyril Soler <csoler@users.sourceforge.net> *
|
||||||
|
* Copyright (C) 2021 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
@ -21,7 +23,9 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <cstdint>
|
||||||
|
|
||||||
|
using RsItemPriority = uint8_t;
|
||||||
|
|
||||||
// This file centralises QoS priorities for all transfer RsItems
|
// This file centralises QoS priorities for all transfer RsItems
|
||||||
//
|
//
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
* *
|
* *
|
||||||
* libretroshare: retroshare core library *
|
* libretroshare: retroshare core library *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org> *
|
* Copyright (C) 2018-2021 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
@ -28,6 +29,9 @@
|
||||||
#include "serialiser/rsserializer.h"
|
#include "serialiser/rsserializer.h"
|
||||||
#include "serialiser/rsserializable.h"
|
#include "serialiser/rsserializable.h"
|
||||||
#include "util/stacktrace.h"
|
#include "util/stacktrace.h"
|
||||||
|
#include "rsitems/itempriorities.h"
|
||||||
|
#include "rsitems/rsserviceids.h"
|
||||||
|
|
||||||
|
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
|
||||||
|
@ -42,8 +46,13 @@ struct RsItem : RsMemoryManagement::SmallObject, RsSerializable
|
||||||
|
|
||||||
virtual ~RsItem();
|
virtual ~RsItem();
|
||||||
|
|
||||||
/// TODO: Do this make sense with the new serialization system?
|
/** TODO: Does the existence of this method make sense with the new
|
||||||
virtual void clear() = 0;
|
* serialization system? **/
|
||||||
|
virtual void clear()
|
||||||
|
{
|
||||||
|
RS_ERR("Called without being overridden, report to developers");
|
||||||
|
print_stacktrace();
|
||||||
|
}
|
||||||
|
|
||||||
/// @deprecated use << ostream operator instead
|
/// @deprecated use << ostream operator instead
|
||||||
RS_DEPRECATED_FOR("<< ostream operator")
|
RS_DEPRECATED_FOR("<< ostream operator")
|
||||||
|
@ -70,14 +79,21 @@ struct RsItem : RsMemoryManagement::SmallObject, RsSerializable
|
||||||
uint8_t PacketType();
|
uint8_t PacketType();
|
||||||
uint8_t PacketSubType() const;
|
uint8_t PacketSubType() const;
|
||||||
|
|
||||||
|
/** For Service Packets, @deprecated use the costructor with priority
|
||||||
|
* paramether instead */
|
||||||
|
RS_DEPRECATED RsItem(uint8_t ver, uint16_t service, uint8_t subtype);
|
||||||
|
|
||||||
/// For Service Packets
|
/// For Service Packets
|
||||||
RsItem(uint8_t ver, uint16_t service, uint8_t subtype);
|
RsItem( uint8_t ver, RsServiceType service, uint8_t subtype,
|
||||||
|
RsItemPriority prio );
|
||||||
|
|
||||||
uint16_t PacketService() const; /* combined Packet class/type (mid 16bits) */
|
uint16_t PacketService() const; /* combined Packet class/type (mid 16bits) */
|
||||||
void setPacketService(uint16_t service);
|
void setPacketService(uint16_t service);
|
||||||
|
|
||||||
inline uint8_t priority_level() const { return _priority_level ;}
|
inline uint8_t priority_level() const { return _priority_level ;}
|
||||||
inline void setPriorityLevel(uint8_t l) { _priority_level = l ;}
|
inline void setPriorityLevel(uint8_t l) { _priority_level = l ;}
|
||||||
|
|
||||||
|
#ifdef RS_DEAD_CODE
|
||||||
/*
|
/*
|
||||||
* TODO: This default implementation should be removed and childs structs
|
* TODO: This default implementation should be removed and childs structs
|
||||||
* implement ::serial_process(...) as soon as all the codebase is ported to
|
* implement ::serial_process(...) as soon as all the codebase is ported to
|
||||||
|
@ -90,11 +106,12 @@ struct RsItem : RsMemoryManagement::SmallObject, RsSerializable
|
||||||
"overriding Class is: ", typeid(*this).name() );
|
"overriding Class is: ", typeid(*this).name() );
|
||||||
print_stacktrace();
|
print_stacktrace();
|
||||||
}
|
}
|
||||||
|
#endif //def RS_DEAD_CODE
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
RsPeerId peerId;
|
RsPeerId peerId;
|
||||||
uint8_t _priority_level;
|
RsItemPriority _priority_level;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// TODO: Do this make sense with the new serialization system?
|
/// TODO: Do this make sense with the new serialization system?
|
||||||
|
@ -108,9 +125,17 @@ public:
|
||||||
uint32_t getRawLength() { return len; }
|
uint32_t getRawLength() { return len; }
|
||||||
void * getRawData() { return data; }
|
void * getRawData() { return data; }
|
||||||
|
|
||||||
virtual void clear() {}
|
// virtual void clear() override {}
|
||||||
virtual std::ostream &print(std::ostream &out, uint16_t indent = 0);
|
virtual std::ostream &print(std::ostream &out, uint16_t indent = 0);
|
||||||
|
|
||||||
|
virtual void serial_process(RsGenericSerializer::SerializeJob,
|
||||||
|
RsGenericSerializer::SerializeContext&) override
|
||||||
|
{
|
||||||
|
RS_ERR( "called by an item using new serialization system ",
|
||||||
|
typeid(*this).name() );
|
||||||
|
print_stacktrace();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void *data;
|
void *data;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
|
|
|
@ -64,6 +64,12 @@ RsItem *RsNxsSerialiser::create_item(uint16_t service_id,uint8_t item_subtype) c
|
||||||
if(service_id != SERVICE_TYPE)
|
if(service_id != SERVICE_TYPE)
|
||||||
return NULL ;
|
return NULL ;
|
||||||
|
|
||||||
|
switch(static_cast<RsNxsSubtype>(item_subtype))
|
||||||
|
{
|
||||||
|
case RsNxsSubtype::PULL_REQUEST:
|
||||||
|
return new RsNxsPullRequestItem(static_cast<RsServiceType>(service_id));
|
||||||
|
}
|
||||||
|
|
||||||
switch(item_subtype)
|
switch(item_subtype)
|
||||||
{
|
{
|
||||||
case RS_PKT_SUBTYPE_NXS_SYNC_GRP_REQ_ITEM: return new RsNxsSyncGrpReqItem(SERVICE_TYPE) ;
|
case RS_PKT_SUBTYPE_NXS_SYNC_GRP_REQ_ITEM: return new RsNxsSyncGrpReqItem(SERVICE_TYPE) ;
|
||||||
|
|
|
@ -3,7 +3,10 @@
|
||||||
* *
|
* *
|
||||||
* libretroshare: retroshare core library *
|
* libretroshare: retroshare core library *
|
||||||
* *
|
* *
|
||||||
* Copyright 2012 Christopher Evi-Parker,Robert Fernie<retroshare@lunamutt.com>*
|
* Copyright (C) 2012 Christopher Evi-Parker *
|
||||||
|
* Copyright (C) 2012 Robert Fernie <retroshare@lunamutt.com> *
|
||||||
|
* Copyright (C) 2021 Gioacchino Mazzurco <gio@altermundi.net> *
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
@ -19,8 +22,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
#ifndef RSNXSITEMS_H
|
#pragma once
|
||||||
#define RSNXSITEMS_H
|
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
|
@ -33,8 +35,13 @@
|
||||||
#include "serialiser/rstlvkeys.h"
|
#include "serialiser/rstlvkeys.h"
|
||||||
#include "gxs/rsgxsdata.h"
|
#include "gxs/rsgxsdata.h"
|
||||||
|
|
||||||
// These items have "flag type" numbers, but this is not used.
|
enum class RsNxsSubtype : uint8_t
|
||||||
|
{
|
||||||
|
PULL_REQUEST = 0x90 /// @see RsNxsPullRequestItem
|
||||||
|
};
|
||||||
|
|
||||||
|
// These items have "flag type" numbers, but this is not used.
|
||||||
|
// TODO: refactor as C++11 enum class
|
||||||
const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_GRP_REQ_ITEM = 0x01;
|
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_ITEM = 0x02;
|
||||||
const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS_ITEM = 0x03;
|
const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS_ITEM = 0x03;
|
||||||
|
@ -47,14 +54,15 @@ 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_TRANSAC_ITEM = 0x40;
|
||||||
const uint8_t RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY_ITEM = 0x80;
|
const uint8_t RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY_ITEM = 0x80;
|
||||||
|
|
||||||
// possibility create second service to deal with this functionality
|
|
||||||
|
|
||||||
|
#ifdef RS_DEAD_CODE
|
||||||
|
// 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_GRP = 0x0001;
|
||||||
const uint8_t RS_PKT_SUBTYPE_EXT_SEARCH_MSG = 0x0002;
|
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_GRP = 0x0004;
|
||||||
const uint8_t RS_PKT_SUBTYPE_EXT_DELETE_MSG = 0x0008;
|
const uint8_t RS_PKT_SUBTYPE_EXT_DELETE_MSG = 0x0008;
|
||||||
const uint8_t RS_PKT_SUBTYPE_EXT_SEARCH_REQ = 0x0010;
|
const uint8_t RS_PKT_SUBTYPE_EXT_SEARCH_REQ = 0x0010;
|
||||||
|
#endif // def RS_DEAD_CODE
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Base class for Network exchange service
|
* Base class for Network exchange service
|
||||||
|
@ -65,15 +73,12 @@ const uint8_t RS_PKT_SUBTYPE_EXT_SEARCH_REQ = 0x0010;
|
||||||
*/
|
*/
|
||||||
class RsNxsItem : public RsItem
|
class RsNxsItem : public RsItem
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RsNxsItem(uint16_t servtype, uint8_t subtype) : RsItem(RS_PKT_VERSION_SERVICE, servtype, subtype), transactionNumber(0)
|
RsNxsItem(uint16_t servtype, uint8_t subtype):
|
||||||
{
|
RsItem(RS_PKT_VERSION_SERVICE, servtype, subtype), transactionNumber(0)
|
||||||
setPriorityLevel(QOS_PRIORITY_RS_GXS_NET);
|
{ setPriorityLevel(QOS_PRIORITY_RS_GXS_NET); }
|
||||||
return;
|
|
||||||
}
|
virtual ~RsNxsItem() = default;
|
||||||
virtual ~RsNxsItem(){}
|
|
||||||
virtual void clear() = 0;
|
|
||||||
|
|
||||||
uint32_t transactionNumber; // set to zero if this is not a transaction item
|
uint32_t transactionNumber; // set to zero if this is not a transaction item
|
||||||
};
|
};
|
||||||
|
@ -362,6 +367,22 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Used to request to a peer pull updates from us ASAP without waiting GXS sync
|
||||||
|
* timer */
|
||||||
|
struct RsNxsPullRequestItem: RsItem
|
||||||
|
{
|
||||||
|
explicit RsNxsPullRequestItem(RsServiceType servtype):
|
||||||
|
RsItem( RS_PKT_VERSION_SERVICE,
|
||||||
|
servtype,
|
||||||
|
static_cast<uint8_t>(RsNxsSubtype::PULL_REQUEST),
|
||||||
|
QOS_PRIORITY_RS_GXS_NET ) {}
|
||||||
|
|
||||||
|
/// @see RsSerializable
|
||||||
|
void serial_process( RsGenericSerializer::SerializeJob,
|
||||||
|
RsGenericSerializer::SerializeContext& ) override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Used to respond to a RsGrpMsgsReq
|
* Used to respond to a RsGrpMsgsReq
|
||||||
|
@ -401,6 +422,7 @@ struct RsNxsMsg : RsNxsItem
|
||||||
RsGxsMsgMetaData* metaData;
|
RsGxsMsgMetaData* metaData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef RS_DEAD_CODE
|
||||||
/*!
|
/*!
|
||||||
* Used to request a search of user data
|
* Used to request a search of user data
|
||||||
*/
|
*/
|
||||||
|
@ -422,7 +444,7 @@ public:
|
||||||
RsTlvBinaryData serviceSearchItem; // service aware of item class
|
RsTlvBinaryData serviceSearchItem; // service aware of item class
|
||||||
uint32_t expiration; // expiration date
|
uint32_t expiration; // expiration date
|
||||||
};
|
};
|
||||||
|
#endif //def RS_DEAD_CODE
|
||||||
|
|
||||||
#ifdef UNUSED_CODE
|
#ifdef UNUSED_CODE
|
||||||
|
|
||||||
|
@ -503,14 +525,12 @@ class RsNxsSerialiser : public RsServiceSerializer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit RsNxsSerialiser(uint16_t servtype) : RsServiceSerializer(servtype), SERVICE_TYPE(servtype) {}
|
explicit RsNxsSerialiser(uint16_t servtype):
|
||||||
virtual ~RsNxsSerialiser() {}
|
RsServiceSerializer(servtype), SERVICE_TYPE(servtype) {}
|
||||||
|
virtual ~RsNxsSerialiser() = default;
|
||||||
|
|
||||||
|
|
||||||
virtual RsItem *create_item(uint16_t service_id,uint8_t item_subtype) const ;
|
virtual RsItem *create_item(uint16_t service_id,uint8_t item_subtype) const ;
|
||||||
protected:
|
protected:
|
||||||
const uint16_t SERVICE_TYPE;
|
const uint16_t SERVICE_TYPE;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // RSNXSITEMS_H
|
|
||||||
|
|
|
@ -118,7 +118,7 @@ void RsServer::rsGlobalShutDown()
|
||||||
// if(mWire) mWire->join();
|
// if(mWire) mWire->join();
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
AuthGPG::exit();
|
AuthPGP::exit();
|
||||||
|
|
||||||
mShutdownCallback(0);
|
mShutdownCallback(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -254,7 +254,7 @@ bool p3Peers::setPeerMaximumRates(const RsPgpId& pid,uint32_t maxUploadRate,uint
|
||||||
|
|
||||||
bool p3Peers::haveSecretKey(const RsPgpId& id)
|
bool p3Peers::haveSecretKey(const RsPgpId& id)
|
||||||
{
|
{
|
||||||
return AuthGPG::getAuthGPG()->haveSecretKey(id);
|
return AuthPGP::haveSecretKey(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* There are too many dependancies of this function
|
/* There are too many dependancies of this function
|
||||||
|
@ -273,7 +273,7 @@ bool p3Peers::getPeerDetails(const RsPeerId& id, RsPeerDetails &d)
|
||||||
if (id == sOwnId)
|
if (id == sOwnId)
|
||||||
{
|
{
|
||||||
mPeerMgr->getOwnNetStatus(ps);
|
mPeerMgr->getOwnNetStatus(ps);
|
||||||
ps.gpg_id = AuthGPG::getAuthGPG()->getGPGOwnId();
|
ps.gpg_id = AuthPGP::getPgpOwnId();
|
||||||
}
|
}
|
||||||
else if (!mPeerMgr->getFriendNetStatus(id, ps))
|
else if (!mPeerMgr->getFriendNetStatus(id, ps))
|
||||||
{
|
{
|
||||||
|
@ -559,17 +559,17 @@ bool p3Peers::isProxyAddress(const uint32_t type, const sockaddr_storage& addr)
|
||||||
|
|
||||||
bool p3Peers::isKeySupported(const RsPgpId& id)
|
bool p3Peers::isKeySupported(const RsPgpId& id)
|
||||||
{
|
{
|
||||||
return AuthGPG::getAuthGPG()->isKeySupported(id);
|
return AuthPGP::isKeySupported(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string p3Peers::getGPGName(const RsPgpId &gpg_id)
|
std::string p3Peers::getGPGName(const RsPgpId &gpg_id)
|
||||||
{
|
{
|
||||||
/* get from mAuthMgr as it should have more peers? */
|
/* get from mAuthMgr as it should have more peers? */
|
||||||
return AuthGPG::getAuthGPG()->getGPGName(gpg_id);
|
return AuthPGP::getPgpName(gpg_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool p3Peers::isPgpFriend(const RsPgpId& pgpId)
|
bool p3Peers::isPgpFriend(const RsPgpId& pgpId)
|
||||||
{ return AuthGPG::getAuthGPG()->isGPGAccepted(pgpId); }
|
{ return AuthPGP::isPGPAccepted(pgpId); }
|
||||||
|
|
||||||
bool p3Peers::isSslOnlyFriend(const RsPeerId& sslId)
|
bool p3Peers::isSslOnlyFriend(const RsPeerId& sslId)
|
||||||
{
|
{
|
||||||
|
@ -597,7 +597,7 @@ std::string p3Peers::getPeerName(const RsPeerId& ssl)
|
||||||
#endif
|
#endif
|
||||||
std::string name;
|
std::string name;
|
||||||
if (ssl == AuthSSL::getAuthSSL()->OwnId())
|
if (ssl == AuthSSL::getAuthSSL()->OwnId())
|
||||||
return AuthGPG::getAuthGPG()->getGPGOwnName();
|
return AuthPGP::getPgpOwnName();
|
||||||
|
|
||||||
if (mPeerMgr->getPeerName(ssl, name))
|
if (mPeerMgr->getPeerName(ssl, name))
|
||||||
{
|
{
|
||||||
|
@ -617,7 +617,7 @@ bool p3Peers::getGPGAllList(std::list<RsPgpId> &ids)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* get from mAuthMgr */
|
/* get from mAuthMgr */
|
||||||
AuthGPG::getAuthGPG()->getGPGAllList(ids);
|
AuthPGP::getPgpAllList(ids);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -628,7 +628,7 @@ bool p3Peers::getGPGValidList(std::list<RsPgpId> &ids)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* get from mAuthMgr */
|
/* get from mAuthMgr */
|
||||||
AuthGPG::getAuthGPG()->getGPGValidList(ids);
|
AuthPGP::getPgpValidList(ids);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,14 +639,14 @@ bool p3Peers::getGPGSignedList(std::list<RsPgpId> &ids)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* get from mAuthMgr */
|
/* get from mAuthMgr */
|
||||||
AuthGPG::getAuthGPG()->getGPGSignedList(ids);
|
AuthPGP::getPgpSignedList(ids);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool p3Peers::getPgpFriendList(std::vector<RsPgpId>& pgpIds)
|
bool p3Peers::getPgpFriendList(std::vector<RsPgpId>& pgpIds)
|
||||||
{
|
{
|
||||||
std::list<RsPgpId> ids;
|
std::list<RsPgpId> ids;
|
||||||
if(AuthGPG::getAuthGPG()->getGPGAcceptedList(ids))
|
if(AuthPGP::getPgpAcceptedList(ids))
|
||||||
{
|
{
|
||||||
pgpIds.clear();
|
pgpIds.clear();
|
||||||
std::copy(ids.begin(), ids.end(), std::back_inserter(pgpIds));
|
std::copy(ids.begin(), ids.end(), std::back_inserter(pgpIds));
|
||||||
|
@ -660,7 +660,7 @@ bool p3Peers::getGPGAcceptedList(std::list<RsPgpId> &ids)
|
||||||
#ifdef P3PEERS_DEBUG
|
#ifdef P3PEERS_DEBUG
|
||||||
std::cerr << "p3Peers::getGPGAcceptedList()" << std::endl;
|
std::cerr << "p3Peers::getGPGAcceptedList()" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
AuthGPG::getAuthGPG()->getGPGAcceptedList(ids);
|
AuthPGP::getPgpAcceptedList(ids);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -676,7 +676,7 @@ bool p3Peers::getAssociatedSSLIds(const RsPgpId &gpg_id, std::list<RsPeerId> &id
|
||||||
|
|
||||||
bool p3Peers::gpgSignData(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen, std::string reason /* = "" */)
|
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);
|
return AuthPGP::SignDataBin(data,len,sign,signlen, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
RsPgpId p3Peers::pgpIdFromFingerprint(const RsPgpFingerprint& fpr)
|
RsPgpId p3Peers::pgpIdFromFingerprint(const RsPgpFingerprint& fpr)
|
||||||
|
@ -691,7 +691,7 @@ bool p3Peers::getGPGDetails(const RsPgpId &pgp_id, RsPeerDetails &d)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* get from mAuthMgr */
|
/* get from mAuthMgr */
|
||||||
bool res = AuthGPG::getAuthGPG()->getGPGDetails(pgp_id, d);
|
bool res = AuthPGP::getPgpDetails(pgp_id, d);
|
||||||
|
|
||||||
d.isOnlyGPGdetail = true ;
|
d.isOnlyGPGdetail = true ;
|
||||||
d.service_perm_flags = mPeerMgr->servicePermissionFlags(pgp_id) ;
|
d.service_perm_flags = mPeerMgr->servicePermissionFlags(pgp_id) ;
|
||||||
|
@ -706,7 +706,7 @@ const RsPgpId& p3Peers::getGPGOwnId()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* get from mAuthMgr */
|
/* get from mAuthMgr */
|
||||||
return AuthGPG::getAuthGPG()->getGPGOwnId();
|
return AuthPGP::getPgpOwnId();
|
||||||
}
|
}
|
||||||
|
|
||||||
RsPgpId p3Peers::getGPGId(const RsPeerId& sslid)
|
RsPgpId p3Peers::getGPGId(const RsPeerId& sslid)
|
||||||
|
@ -718,7 +718,7 @@ RsPgpId p3Peers::getGPGId(const RsPeerId& sslid)
|
||||||
/* get from mAuthMgr */
|
/* get from mAuthMgr */
|
||||||
if (sslid == AuthSSL::getAuthSSL()->OwnId())
|
if (sslid == AuthSSL::getAuthSSL()->OwnId())
|
||||||
{
|
{
|
||||||
return AuthGPG::getAuthGPG()->getGPGOwnId();
|
return AuthPGP::getPgpOwnId();
|
||||||
}
|
}
|
||||||
peerState pcs;
|
peerState pcs;
|
||||||
if (mPeerMgr->getFriendNetStatus(sslid, pcs))
|
if (mPeerMgr->getFriendNetStatus(sslid, pcs))
|
||||||
|
@ -739,12 +739,12 @@ bool p3Peers::addFriend(const RsPeerId &ssl_id, const RsPgpId &gpg_id,ServicePe
|
||||||
#ifdef P3PEERS_DEBUG
|
#ifdef P3PEERS_DEBUG
|
||||||
std::cerr << "p3Peers::addFriend() with : id : " << id << "; gpg_id : " << gpg_id << std::endl;
|
std::cerr << "p3Peers::addFriend() with : id : " << id << "; gpg_id : " << gpg_id << std::endl;
|
||||||
#endif
|
#endif
|
||||||
if(AuthGPG::getAuthGPG()->isGPGId(gpg_id))
|
if(AuthPGP::isPGPId(gpg_id))
|
||||||
{
|
{
|
||||||
#ifdef P3PEERS_DEBUG
|
#ifdef P3PEERS_DEBUG
|
||||||
std::cerr << "p3Peers::addFriend() Authorising GPG Id: " << gpg_id << std::endl;
|
std::cerr << "p3Peers::addFriend() Authorising GPG Id: " << gpg_id << std::endl;
|
||||||
#endif
|
#endif
|
||||||
if (AuthGPG::getAuthGPG()->AllowConnection(gpg_id, true))
|
if (AuthPGP::AllowConnection(gpg_id, true))
|
||||||
{
|
{
|
||||||
#ifdef P3PEERS_DEBUG
|
#ifdef P3PEERS_DEBUG
|
||||||
std::cerr << "p3Peers::addFriend() Authorization OK." << std::endl;
|
std::cerr << "p3Peers::addFriend() Authorization OK." << std::endl;
|
||||||
|
@ -797,7 +797,7 @@ bool p3Peers::addSslOnlyFriend( const RsPeerId& sslId, const RsPgpId& pgp_id,con
|
||||||
|
|
||||||
bool p3Peers::removeKeysFromPGPKeyring(const std::set<RsPgpId>& pgp_ids,std::string& backup_file,uint32_t& error_code)
|
bool p3Peers::removeKeysFromPGPKeyring(const std::set<RsPgpId>& pgp_ids,std::string& backup_file,uint32_t& error_code)
|
||||||
{
|
{
|
||||||
return AuthGPG::getAuthGPG()->removeKeysFromPGPKeyring(pgp_ids,backup_file,error_code) ;
|
return AuthPGP::removeKeysFromPGPKeyring(pgp_ids,backup_file,error_code) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool p3Peers::removeFriendLocation(const RsPeerId &sslId)
|
bool p3Peers::removeFriendLocation(const RsPeerId &sslId)
|
||||||
|
@ -817,7 +817,7 @@ bool p3Peers::removeFriend(const RsPgpId& gpgId)
|
||||||
#ifdef P3PEERS_DEBUG
|
#ifdef P3PEERS_DEBUG
|
||||||
std::cerr << "p3Peers::removeFriend() " << gpgId << std::endl;
|
std::cerr << "p3Peers::removeFriend() " << gpgId << std::endl;
|
||||||
#endif
|
#endif
|
||||||
if (gpgId == AuthGPG::getAuthGPG()->getGPGOwnId()) {
|
if (gpgId == AuthPGP::getPgpOwnId()) {
|
||||||
std::cerr << "p3Peers::removeFriend() ERROR we're not going to remove our own GPG id." << std::endl;
|
std::cerr << "p3Peers::removeFriend() ERROR we're not going to remove our own GPG id." << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -825,7 +825,7 @@ bool p3Peers::removeFriend(const RsPgpId& gpgId)
|
||||||
#ifdef P3PEERS_DEBUG
|
#ifdef P3PEERS_DEBUG
|
||||||
std::cerr << "p3Peers::removeFriend() Removing GPG Id: " << gpgId << std::endl;
|
std::cerr << "p3Peers::removeFriend() Removing GPG Id: " << gpgId << std::endl;
|
||||||
#endif
|
#endif
|
||||||
if (AuthGPG::getAuthGPG()->AllowConnection(gpgId, false))
|
if (AuthPGP::AllowConnection(gpgId, false))
|
||||||
{
|
{
|
||||||
#ifdef P3PEERS_DEBUG
|
#ifdef P3PEERS_DEBUG
|
||||||
std::cerr << "p3Peers::removeFriend() OK." << std::endl;
|
std::cerr << "p3Peers::removeFriend() OK." << std::endl;
|
||||||
|
@ -1113,9 +1113,7 @@ std::string p3Peers::getPGPKey(const RsPgpId& pgp_id,bool include_signatures)
|
||||||
rs_owner_ptr<unsigned char> mem_block = nullptr;
|
rs_owner_ptr<unsigned char> mem_block = nullptr;
|
||||||
size_t mem_block_size = 0;
|
size_t mem_block_size = 0;
|
||||||
|
|
||||||
if( !AuthGPG::getAuthGPG()->exportPublicKey(
|
if( !AuthPGP::exportPublicKey( RsPgpId(pgp_id), mem_block, mem_block_size, false, include_signatures ) )
|
||||||
RsPgpId(pgp_id), mem_block, mem_block_size,
|
|
||||||
false, include_signatures ) )
|
|
||||||
{
|
{
|
||||||
RsErr() << __PRETTY_FUNCTION__
|
RsErr() << __PRETTY_FUNCTION__
|
||||||
<< " Failure retriving certificate for id " << pgp_id
|
<< " Failure retriving certificate for id " << pgp_id
|
||||||
|
@ -1146,8 +1144,7 @@ bool p3Peers::GetPGPBase64StringAndCheckSum(
|
||||||
|
|
||||||
rs_owner_ptr<unsigned char> mem_block = nullptr;
|
rs_owner_ptr<unsigned char> mem_block = nullptr;
|
||||||
size_t mem_block_size = 0;
|
size_t mem_block_size = 0;
|
||||||
if(!AuthGPG::getAuthGPG()->exportPublicKey(
|
if(!AuthPGP::exportPublicKey( gpg_id,mem_block,mem_block_size,false,false ))
|
||||||
gpg_id,mem_block,mem_block_size,false,false ))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
RsBase64::encode(mem_block, mem_block_size, gpg_base64_string, true, false);
|
RsBase64::encode(mem_block, mem_block_size, gpg_base64_string, true, false);
|
||||||
|
@ -1644,7 +1641,7 @@ std::string p3Peers::GetRetroshareInvite( const RsPeerId& sslId, RetroshareInvit
|
||||||
unsigned char *mem_block = nullptr;
|
unsigned char *mem_block = nullptr;
|
||||||
size_t mem_block_size = 0;
|
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) ))
|
if(!AuthPGP::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
|
std::cerr << "Cannot output certificate for id \"" << detail.gpg_id
|
||||||
<< "\". Sorry." << std::endl;
|
<< "\". Sorry." << std::endl;
|
||||||
|
@ -1680,7 +1677,7 @@ bool p3Peers::loadCertificateFromString(
|
||||||
}
|
}
|
||||||
|
|
||||||
RsPgpId gpgid;
|
RsPgpId gpgid;
|
||||||
bool res = AuthGPG::getAuthGPG()->LoadCertificateFromString( crt->armouredPGPKey(), gpgid, error_string );
|
bool res = AuthPGP::LoadCertificateFromString( crt->armouredPGPKey(), gpgid, error_string );
|
||||||
|
|
||||||
gpg_id = gpgid;
|
gpg_id = gpgid;
|
||||||
ssl_id = crt->sslid();
|
ssl_id = crt->sslid();
|
||||||
|
@ -1697,7 +1694,7 @@ bool p3Peers::loadCertificateFromString(
|
||||||
}
|
}
|
||||||
bool p3Peers::loadPgpKeyFromBinaryData( const unsigned char *bin_key_data,uint32_t bin_key_len, RsPgpId& gpg_id, std::string& error_string )
|
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 );
|
bool res = AuthPGP::LoadPGPKeyFromBinaryData( bin_key_data,bin_key_len, gpg_id, error_string );
|
||||||
|
|
||||||
if(res)
|
if(res)
|
||||||
mPeerMgr->notifyPgpKeyReceived(gpg_id);
|
mPeerMgr->notifyPgpKeyReceived(gpg_id);
|
||||||
|
@ -1716,9 +1713,7 @@ bool p3Peers::loadDetailsFromStringCert( const std::string &certstr,
|
||||||
|
|
||||||
RsCertificate& cert = *certPtr;
|
RsCertificate& cert = *certPtr;
|
||||||
|
|
||||||
if(!AuthGPG::getAuthGPG()->getGPGDetailsFromBinaryBlock(
|
if(!AuthPGP::getPgpDetailsFromBinaryBlock( cert.pgp_key(), cert.pgp_key_size(), pd.gpg_id, pd.name, pd.gpgSigners ))
|
||||||
cert.pgp_key(), cert.pgp_key_size(),
|
|
||||||
pd.gpg_id, pd.name, pd.gpgSigners ))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Dbg4() << __PRETTY_FUNCTION__ << " Parsing cert for sslid, location, ext "
|
Dbg4() << __PRETTY_FUNCTION__ << " Parsing cert for sslid, location, ext "
|
||||||
|
@ -1758,11 +1753,11 @@ bool p3Peers::loadDetailsFromStringCert( const std::string &certstr,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool p3Peers::cleanCertificate(const std::string &certstr, std::string &cleanCert,bool& is_short_format,uint32_t& error_code)
|
bool p3Peers::cleanCertificate(const std::string &certstr, std::string &cleanCert,bool& is_short_format,uint32_t& error_code,RsPeerDetails& details)
|
||||||
{
|
{
|
||||||
RsCertificate::Format format ;
|
RsCertificate::Format format ;
|
||||||
|
|
||||||
bool res = RsCertificate::cleanCertificate(certstr,cleanCert,format,error_code,true) ;
|
bool res = RsCertificate::cleanCertificate(certstr,cleanCert,format,error_code,true,details) ;
|
||||||
|
|
||||||
if(format == RsCertificate::RS_CERTIFICATE_RADIX)
|
if(format == RsCertificate::RS_CERTIFICATE_RADIX)
|
||||||
is_short_format = false;
|
is_short_format = false;
|
||||||
|
@ -1796,7 +1791,7 @@ bool p3Peers::signGPGCertificate(const RsPgpId &id, const std::string &gpg_pass
|
||||||
rsNotify->cachePgpPassphrase(gpg_passphrase);
|
rsNotify->cachePgpPassphrase(gpg_passphrase);
|
||||||
rsNotify->setDisableAskPassword(true);
|
rsNotify->setDisableAskPassword(true);
|
||||||
|
|
||||||
bool res = AuthGPG::getAuthGPG()->SignCertificateLevel0(id);
|
bool res = AuthPGP::SignCertificateLevel0(id);
|
||||||
|
|
||||||
rsNotify->clearPgpPassphrase();
|
rsNotify->clearPgpPassphrase();
|
||||||
rsNotify->setDisableAskPassword(false);
|
rsNotify->setDisableAskPassword(false);
|
||||||
|
@ -1810,7 +1805,7 @@ bool p3Peers::trustGPGCertificate(const RsPgpId &id, uint32_t trustlvl)
|
||||||
std::cerr << "p3Peers::TrustCertificate() " << id;
|
std::cerr << "p3Peers::TrustCertificate() " << id;
|
||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
#endif
|
#endif
|
||||||
return AuthGPG::getAuthGPG()->TrustCertificate(id, trustlvl);
|
return AuthPGP::TrustCertificate(id, trustlvl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Group Stuff */
|
/* Group Stuff */
|
||||||
|
|
|
@ -163,7 +163,7 @@ public:
|
||||||
virtual bool loadPgpKeyFromBinaryData( const unsigned char *bin_key_data,uint32_t bin_key_len, RsPgpId& gpg_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 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 bool cleanCertificate(const std::string &certstr, std::string &cleanCert, bool &is_short_format, uint32_t& error_code, RsPeerDetails& details) override;
|
||||||
virtual std::string saveCertificateToString(const RsPeerId &id) override;
|
virtual std::string saveCertificateToString(const RsPeerId &id) override;
|
||||||
|
|
||||||
virtual bool signGPGCertificate(const RsPgpId &id,const std::string& gpg_passphrase) override;
|
virtual bool signGPGCertificate(const RsPgpId &id,const std::string& gpg_passphrase) override;
|
||||||
|
|
|
@ -140,7 +140,7 @@ bool p3ServerConfig::setConfigurationOption(uint32_t key, const std::string &opt
|
||||||
int p3ServerConfig::getConfigNetStatus(RsConfigNetStatus &status)
|
int p3ServerConfig::getConfigNetStatus(RsConfigNetStatus &status)
|
||||||
{
|
{
|
||||||
status.ownId = AuthSSL::getAuthSSL()->OwnId();
|
status.ownId = AuthSSL::getAuthSSL()->OwnId();
|
||||||
status.ownName = AuthGPG::getAuthGPG()->getGPGOwnName();
|
status.ownName = AuthPGP::getPgpOwnName();
|
||||||
|
|
||||||
// Details from PeerMgr.
|
// Details from PeerMgr.
|
||||||
peerState pstate;
|
peerState pstate;
|
||||||
|
|
|
@ -32,12 +32,12 @@
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <system_error>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "retroshare/rsinit.h"
|
#include "retroshare/rsinit.h"
|
||||||
#include "rsaccounts.h"
|
#include "rsaccounts.h"
|
||||||
|
#include "util/rsdebug.h"
|
||||||
#include "util/rsdir.h"
|
#include "util/rsdir.h"
|
||||||
#include "util/rsstring.h"
|
#include "util/rsstring.h"
|
||||||
#include "util/folderiterator.h"
|
#include "util/folderiterator.h"
|
||||||
|
@ -48,6 +48,11 @@
|
||||||
|
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
# include "rs_android/rsjni.hpp"
|
||||||
|
# include "rs_android/retroshareserviceandroid.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
// Global singleton declaration of data.
|
// Global singleton declaration of data.
|
||||||
RsAccountsDetail* RsAccounts::rsAccountsDetails = nullptr;
|
RsAccountsDetail* RsAccounts::rsAccountsDetails = nullptr;
|
||||||
|
|
||||||
|
@ -328,22 +333,7 @@ bool RsAccountsDetail::defaultBaseDirectory()
|
||||||
{
|
{
|
||||||
std::string basedir;
|
std::string basedir;
|
||||||
|
|
||||||
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
#ifdef WINDOWS_SYS
|
||||||
#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())
|
if (RsInit::isPortable())
|
||||||
{
|
{
|
||||||
// use directory "Data" in portable version
|
// use directory "Data" in portable version
|
||||||
|
@ -375,13 +365,53 @@ bool RsAccountsDetail::defaultBaseDirectory()
|
||||||
}
|
}
|
||||||
basedir += "\\RetroShare";
|
basedir += "\\RetroShare";
|
||||||
}
|
}
|
||||||
#endif
|
#elif defined (__ANDROID__) // def WINDOWS_SYS
|
||||||
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
|
||||||
|
struct ApplicationInfo
|
||||||
|
{
|
||||||
|
static constexpr auto Name()
|
||||||
|
{ return "android/content/pm/ApplicationInfo"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
auto uenv = jni::GetAttachedEnv(RsJni::getVM());
|
||||||
|
JNIEnv& env = *uenv;
|
||||||
|
auto androidContext = RetroShareServiceAndroid::getAndroidContext(env);
|
||||||
|
auto& contextClass =
|
||||||
|
jni::Class<RetroShareServiceAndroid::Context>::Singleton(env);
|
||||||
|
|
||||||
|
auto& applicationInfoClass = jni::Class<ApplicationInfo>::Singleton(env);
|
||||||
|
|
||||||
|
auto getApplicationInfo =
|
||||||
|
contextClass.GetMethod<jni::Object<ApplicationInfo> ()>(
|
||||||
|
env, "getApplicationInfo" );
|
||||||
|
|
||||||
|
auto applicationInfo = androidContext.Call(env, getApplicationInfo);
|
||||||
|
|
||||||
|
auto dataDirField = jni::Field<ApplicationInfo, jni::String>(
|
||||||
|
env, applicationInfoClass, "dataDir" );
|
||||||
|
|
||||||
|
jni::Local<jni::String> dataDir = applicationInfo.Get<jni::String>(
|
||||||
|
env, dataDirField );
|
||||||
|
|
||||||
|
basedir = jni::Make<std::string>(env, dataDir) + "/.retroshare/";
|
||||||
|
|
||||||
|
#else // def WINDOWS_SYS, if defined (__ANDROID__)
|
||||||
|
// unix: homedir + /.retroshare
|
||||||
|
char* h = getenv("HOME");
|
||||||
|
if(h == nullptr)
|
||||||
|
{
|
||||||
|
RS_ERR("cannot determine $HOME dir");
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
|
||||||
|
basedir = h;
|
||||||
|
basedir += "/.retroshare";
|
||||||
|
#endif // def WINDOWS_SYS
|
||||||
|
|
||||||
/* store to class variable */
|
/* store to class variable */
|
||||||
mBaseDirectory = basedir;
|
mBaseDirectory = basedir;
|
||||||
std::cerr << "defaultBaseDirectory() = " << mBaseDirectory;
|
|
||||||
std::cerr << std::endl;
|
RS_INFO(mBaseDirectory);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -701,10 +731,10 @@ static bool checkAccount(const std::string &accountdir, AccountDetails &account,
|
||||||
if(! RsAccounts::GetPGPLoginDetails(account.mPgpId, account.mPgpName, account.mPgpEmail))
|
if(! RsAccounts::GetPGPLoginDetails(account.mPgpId, account.mPgpName, account.mPgpEmail))
|
||||||
return false ;
|
return false ;
|
||||||
|
|
||||||
if(!AuthGPG::getAuthGPG()->haveSecretKey(account.mPgpId))
|
if(!AuthPGP::haveSecretKey(account.mPgpId))
|
||||||
return false ;
|
return false ;
|
||||||
|
|
||||||
if(!AuthGPG::getAuthGPG()->isKeySupported(account.mPgpId))
|
if(!AuthPGP::isKeySupported(account.mPgpId))
|
||||||
{
|
{
|
||||||
std::string keystring = account.mPgpId.toStdString() + " " + account.mPgpName + "<" + account.mPgpEmail ;
|
std::string keystring = account.mPgpId.toStdString() + " " + account.mPgpName + "<" + account.mPgpEmail ;
|
||||||
unsupported_keys[keystring].push_back("Location: " + account.mLocation + " (" + account.mSslId.toStdString() + ")") ;
|
unsupported_keys[keystring].push_back("Location: " + account.mLocation + " (" + account.mSslId.toStdString() + ")") ;
|
||||||
|
@ -811,14 +841,15 @@ static bool checkAccount(const std::string &accountdir, AccountDetails &account,
|
||||||
|
|
||||||
/* Use RetroShare's exe dir */
|
/* Use RetroShare's exe dir */
|
||||||
dataDirectory = ".";
|
dataDirectory = ".";
|
||||||
#elif defined(ANDROID)
|
#elif defined(__ANDROID__)
|
||||||
|
// TODO: This is probably not really used on Android
|
||||||
dataDirectory = PathBaseDirectory()+"/usr/share/retroshare";
|
dataDirectory = PathBaseDirectory()+"/usr/share/retroshare";
|
||||||
#elif defined(DATA_DIR)
|
#elif defined(RS_DATA_DIR)
|
||||||
// cppcheck-suppress ConfigurationNotChecked
|
// cppcheck-suppress ConfigurationNotChecked
|
||||||
dataDirectory = DATA_DIR;
|
dataDirectory = RS_DATA_DIR;
|
||||||
// For all other OS the data directory must be set in libretroshare.pro
|
// For all other OS the data directory must be set in libretroshare.pro
|
||||||
#else
|
#else
|
||||||
# error "For your target OS automatic data dir discovery is not supported, cannot compile if DATA_DIR variable not set."
|
# error "For your target OS automatic data dir discovery is not supported, cannot compile if RS_DATA_DIR variable not set."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!check)
|
if (!check)
|
||||||
|
@ -851,8 +882,9 @@ static bool checkAccount(const std::string &accountdir, AccountDetails &account,
|
||||||
|
|
||||||
|
|
||||||
/* Generating GPGme Account */
|
/* Generating GPGme Account */
|
||||||
int RsAccountsDetail::GetPGPLogins(std::list<RsPgpId> &pgpIds) {
|
int RsAccountsDetail::GetPGPLogins(std::list<RsPgpId>& pgpIds)
|
||||||
AuthGPG::getAuthGPG()->availableGPGCertificatesWithPrivateKeys(pgpIds);
|
{
|
||||||
|
AuthPGP::availablePgpCertificatesWithPrivateKeys(pgpIds);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -863,10 +895,10 @@ int RsAccountsDetail::GetPGPLoginDetails(const RsPgpId& id, std::string &na
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool ok = true ;
|
bool ok = true ;
|
||||||
name = AuthGPG::getAuthGPG()->getGPGName(id,&ok);
|
name = AuthPGP::getPgpName(id,&ok);
|
||||||
if(!ok)
|
if(!ok)
|
||||||
return 0 ;
|
return 0 ;
|
||||||
email = AuthGPG::getAuthGPG()->getGPGEmail(id,&ok);
|
email = AuthPGP::getPgpEmail(id,&ok);
|
||||||
if(!ok)
|
if(!ok)
|
||||||
return 0 ;
|
return 0 ;
|
||||||
|
|
||||||
|
@ -886,7 +918,7 @@ bool RsAccountsDetail::SelectPGPAccount(const RsPgpId& pgpId)
|
||||||
{
|
{
|
||||||
bool retVal = false;
|
bool retVal = false;
|
||||||
|
|
||||||
if (0 < AuthGPG::getAuthGPG() -> GPGInit(pgpId))
|
if (0 < AuthPGP::PgpInit(pgpId))
|
||||||
{
|
{
|
||||||
retVal = true;
|
retVal = true;
|
||||||
#ifdef DEBUG_ACCOUNTS
|
#ifdef DEBUG_ACCOUNTS
|
||||||
|
@ -906,7 +938,7 @@ bool RsAccountsDetail::SelectPGPAccount(const RsPgpId& pgpId)
|
||||||
|
|
||||||
bool RsAccountsDetail::GeneratePGPCertificate(const std::string& name, const std::string& email, const std::string& passwd, RsPgpId &pgpId, const int keynumbits, std::string &errString)
|
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);
|
return AuthPGP::GeneratePgpCertificate(name, email, passwd, pgpId, keynumbits, errString);
|
||||||
}
|
}
|
||||||
|
|
||||||
// PGP Support Functions.
|
// PGP Support Functions.
|
||||||
|
@ -918,29 +950,34 @@ void RsAccountsDetail::getUnsupportedKeys(std::map<std::string,std::vector<std::
|
||||||
|
|
||||||
bool RsAccountsDetail::exportIdentity(const std::string& fname,const RsPgpId& id)
|
bool RsAccountsDetail::exportIdentity(const std::string& fname,const RsPgpId& id)
|
||||||
{
|
{
|
||||||
return AuthGPG::getAuthGPG()->exportProfile(fname,id);
|
return AuthPGP::exportProfile(fname,id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RsAccountsDetail::importIdentity(const std::string& fname,RsPgpId& id,std::string& import_error)
|
bool RsAccountsDetail::importIdentity(const std::string& fname,RsPgpId& id,std::string& import_error)
|
||||||
{
|
{
|
||||||
return AuthGPG::getAuthGPG()->importProfile(fname,id,import_error);
|
return AuthPGP::importProfile(fname,id,import_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RsAccountsDetail::importIdentityFromString(const std::string &data, RsPgpId &imported_pgp_id, std::string &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);
|
return AuthPGP::importProfileFromString(data, imported_pgp_id, import_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RsAccountsDetail::exportIdentityToString(
|
bool RsAccountsDetail::exportIdentityToString(
|
||||||
std::string& data, const RsPgpId& pgpId, bool includeSignatures,
|
std::string& data, const RsPgpId& pgpId, bool includeSignatures,
|
||||||
std::string& errorMsg )
|
std::string& errorMsg )
|
||||||
{
|
{
|
||||||
return AuthGPG::getAuthGPG()->exportIdentityToString(
|
return AuthPGP::exportIdentityToString(
|
||||||
data, pgpId, includeSignatures, errorMsg );
|
data, pgpId, includeSignatures, errorMsg );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RsAccountsDetail::copyGnuPGKeyrings()
|
bool RsAccountsDetail::copyGnuPGKeyrings()
|
||||||
{
|
{
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
RS_ERR(std::errc::not_supported);
|
||||||
|
print_stacktrace();
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
std::string pgp_dir = PathPGPDirectory() ;
|
std::string pgp_dir = PathPGPDirectory() ;
|
||||||
|
|
||||||
if(!RsDirUtil::checkCreateDirectory(pgp_dir))
|
if(!RsDirUtil::checkCreateDirectory(pgp_dir))
|
||||||
|
@ -992,6 +1029,7 @@ bool RsAccountsDetail::copyGnuPGKeyrings()
|
||||||
}
|
}
|
||||||
|
|
||||||
return true ;
|
return true ;
|
||||||
|
#endif // def __ANDROID__
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1020,7 +1058,7 @@ bool RsAccountsDetail::GenerateSSLCertificate(const RsPgpId& pgp_id, const s
|
||||||
|
|
||||||
int nbits = 4096;
|
int nbits = 4096;
|
||||||
|
|
||||||
//std::string pgp_name = AuthGPG::getAuthGPG()->getGPGName(pgp_id);
|
//std::string pgp_name = AuthGPG::getGPGName(pgp_id);
|
||||||
|
|
||||||
// Create the filename .....
|
// Create the filename .....
|
||||||
// Temporary Directory for creating files....
|
// Temporary Directory for creating files....
|
||||||
|
@ -1295,7 +1333,7 @@ bool RsAccounts::init(const std::string& opt_base_dir,int& error_code)
|
||||||
if(!RsDirUtil::checkCreateDirectory(pgp_dir))
|
if(!RsDirUtil::checkCreateDirectory(pgp_dir))
|
||||||
throw std::runtime_error("Cannot create pgp directory " + pgp_dir) ;
|
throw std::runtime_error("Cannot create pgp directory " + pgp_dir) ;
|
||||||
|
|
||||||
AuthGPG::init( pgp_dir + "/retroshare_public_keyring.gpg",
|
AuthPGP::init( pgp_dir + "/retroshare_public_keyring.gpg",
|
||||||
pgp_dir + "/retroshare_secret_keyring.gpg",
|
pgp_dir + "/retroshare_secret_keyring.gpg",
|
||||||
pgp_dir + "/retroshare_trustdb.gpg",
|
pgp_dir + "/retroshare_trustdb.gpg",
|
||||||
pgp_dir + "/lock");
|
pgp_dir + "/lock");
|
||||||
|
|
|
@ -32,8 +32,9 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
# include <QFile> // To install bdboot.txt
|
# include <jni/jni.hpp>
|
||||||
# include <QString> // for QString::fromStdString(...)
|
# include "rs_android/rsjni.hpp"
|
||||||
|
# include "rs_android/retroshareserviceandroid.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "util/argstream.h"
|
#include "util/argstream.h"
|
||||||
|
@ -196,7 +197,7 @@ static const int SSLPWD_LEN = 64;
|
||||||
|
|
||||||
void RsInit::InitRsConfig()
|
void RsInit::InitRsConfig()
|
||||||
{
|
{
|
||||||
RsInfo() << " libretroshare version: " << RS_HUMAN_READABLE_VERSION
|
RsInfo() << "libretroshare version: " << RS_HUMAN_READABLE_VERSION
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
rsInitConfig = new RsInitConfig;
|
rsInitConfig = new RsInitConfig;
|
||||||
|
@ -514,7 +515,7 @@ RsInit::LoadCertificateStatus RsInit::LockAndLoadCertificates(
|
||||||
if(!RsAccounts::GetAccountDetails(accountId, pgpId, pgpName, pgpEmail, location))
|
if(!RsAccounts::GetAccountDetails(accountId, pgpId, pgpName, pgpEmail, location))
|
||||||
throw RsInit::ERR_UNKNOWN; // invalid PreferredAccount;
|
throw RsInit::ERR_UNKNOWN; // invalid PreferredAccount;
|
||||||
|
|
||||||
if(0 == AuthGPG::getAuthGPG() -> GPGInit(pgpId))
|
if(0 == AuthPGP::PgpInit(pgpId))
|
||||||
throw RsInit::ERR_UNKNOWN; // PGP Error.
|
throw RsInit::ERR_UNKNOWN; // PGP Error.
|
||||||
|
|
||||||
LoadCertificateStatus retVal =
|
LoadCertificateStatus retVal =
|
||||||
|
@ -914,8 +915,8 @@ int RsServer::StartupRetroShare()
|
||||||
/* History Manager */
|
/* History Manager */
|
||||||
mHistoryMgr = new p3HistoryMgr();
|
mHistoryMgr = new p3HistoryMgr();
|
||||||
mPeerMgr = new p3PeerMgrIMPL( AuthSSL::getAuthSSL()->OwnId(),
|
mPeerMgr = new p3PeerMgrIMPL( AuthSSL::getAuthSSL()->OwnId(),
|
||||||
AuthGPG::getAuthGPG()->getGPGOwnId(),
|
AuthPGP::getPgpOwnId(),
|
||||||
AuthGPG::getAuthGPG()->getGPGOwnName(),
|
AuthPGP::getPgpOwnName(),
|
||||||
AuthSSL::getAuthSSL()->getOwnLocation());
|
AuthSSL::getAuthSSL()->getOwnLocation());
|
||||||
mNetMgr = new p3NetMgrIMPL();
|
mNetMgr = new p3NetMgrIMPL();
|
||||||
mLinkMgr = new p3LinkMgrIMPL(mPeerMgr, mNetMgr);
|
mLinkMgr = new p3LinkMgrIMPL(mPeerMgr, mNetMgr);
|
||||||
|
@ -1014,32 +1015,32 @@ int RsServer::StartupRetroShare()
|
||||||
uint64_t tmp_size ;
|
uint64_t tmp_size ;
|
||||||
if (!RsDirUtil::checkFile(bootstrapfile,tmp_size,true))
|
if (!RsDirUtil::checkFile(bootstrapfile,tmp_size,true))
|
||||||
{
|
{
|
||||||
std::cerr << "DHT bootstrap file not in ConfigDir: " << bootstrapfile
|
RS_INFO("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();
|
#ifdef __ANDROID__
|
||||||
}
|
auto uenv = jni::GetAttachedEnv(RsJni::getVM());
|
||||||
#else
|
JNIEnv& env = *uenv;
|
||||||
|
|
||||||
|
using AContext = RetroShareServiceAndroid::Context;
|
||||||
|
|
||||||
|
auto& assetHelperClass = jni::Class<RsJni::AssetHelper>::Singleton(env);
|
||||||
|
|
||||||
|
static auto copyAsset =
|
||||||
|
assetHelperClass.GetStaticMethod<
|
||||||
|
jni::jboolean(jni::Object<AContext>, jni::String, jni::String)>(
|
||||||
|
env, "copyAsset" );
|
||||||
|
|
||||||
|
auto androidContext = RetroShareServiceAndroid::getAndroidContext(env);
|
||||||
|
|
||||||
|
jni::jboolean result = assetHelperClass.Call(
|
||||||
|
env, copyAsset,
|
||||||
|
androidContext,
|
||||||
|
jni::Make<jni::String>(env, "values/bdboot.txt"),
|
||||||
|
jni::Make<jni::String>(env, bootstrapfile) );
|
||||||
|
|
||||||
|
if(!result) RS_ERR("Failure installing ", bootstrapfile);
|
||||||
|
|
||||||
|
#else // def __ANDROID__
|
||||||
std::cerr << "Checking for Installation DHT bootstrap file " << installfile << std::endl;
|
std::cerr << "Checking for Installation DHT bootstrap file " << installfile << std::endl;
|
||||||
if ((installfile != "") && (RsDirUtil::checkFile(installfile,tmp_size)))
|
if ((installfile != "") && (RsDirUtil::checkFile(installfile,tmp_size)))
|
||||||
{
|
{
|
||||||
|
@ -1615,7 +1616,8 @@ int RsServer::StartupRetroShare()
|
||||||
|
|
||||||
//mConfigMgr->addConfiguration("ftserver.cfg", ftserver);
|
//mConfigMgr->addConfiguration("ftserver.cfg", ftserver);
|
||||||
//
|
//
|
||||||
mConfigMgr->addConfiguration("gpg_prefs.cfg" , AuthGPG::getAuthGPG());
|
AuthPGP::registerToConfigMgr(std::string("gpg_prefs.cfg"),mConfigMgr);
|
||||||
|
|
||||||
mConfigMgr->addConfiguration("gxsnettunnel.cfg", mGxsNetTunnel);
|
mConfigMgr->addConfiguration("gxsnettunnel.cfg", mGxsNetTunnel);
|
||||||
mConfigMgr->addConfiguration("peers.cfg" , mPeerMgr);
|
mConfigMgr->addConfiguration("peers.cfg" , mPeerMgr);
|
||||||
mConfigMgr->addConfiguration("general.cfg" , mGeneralConfig);
|
mConfigMgr->addConfiguration("general.cfg" , mGeneralConfig);
|
||||||
|
@ -1801,7 +1803,7 @@ int RsServer::StartupRetroShare()
|
||||||
/* Add AuthGPG services */
|
/* Add AuthGPG services */
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
|
|
||||||
//AuthGPG::getAuthGPG()->addService(mDisc);
|
//AuthGPG::addService(mDisc);
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/* Force Any Last Configuration Options */
|
/* Force Any Last Configuration Options */
|
||||||
|
|
|
@ -60,8 +60,7 @@ bool RsLoginHandler::checkAndStoreSSLPasswdIntoGPGFile(
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ok = AuthGPG::getAuthGPG()->encryptTextToFile(
|
bool ok = AuthPGP::encryptTextToFile( ssl_passwd, getSSLPasswdFileName(ssl_id));
|
||||||
ssl_passwd, getSSLPasswdFileName(ssl_id));
|
|
||||||
|
|
||||||
if (!ok) std::cerr << "Encrypting went wrong !" << std::endl;
|
if (!ok) std::cerr << "Encrypting went wrong !" << std::endl;
|
||||||
|
|
||||||
|
@ -90,7 +89,7 @@ bool RsLoginHandler::getSSLPasswdFromGPGFile(const RsPeerId& ssl_id,std::string&
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::string plain;
|
std::string plain;
|
||||||
if ( AuthGPG::getAuthGPG()->decryptTextFromFile( plain, getSSLPasswdFileName(ssl_id)) )
|
if ( AuthPGP::decryptTextFromFile( plain, getSSLPasswdFileName(ssl_id)) )
|
||||||
{
|
{
|
||||||
sslPassword = plain;
|
sslPassword = plain;
|
||||||
#ifdef DEBUG_RSLOGINHANDLER
|
#ifdef DEBUG_RSLOGINHANDLER
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
* *
|
* *
|
||||||
* libretroshare: retroshare core library *
|
* libretroshare: retroshare core library *
|
||||||
* *
|
* *
|
||||||
* Copyright 2007-2008 by Robert Fernie <retroshare@lunamutt.com> *
|
* Copyright (C) 2007-2008 Robert Fernie <retroshare@lunamutt.com> *
|
||||||
|
* Copyright (C) 2021 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
@ -20,21 +22,20 @@
|
||||||
* *
|
* *
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "serialiser/rsbaseserial.h"
|
#include <cmath>
|
||||||
|
|
||||||
#include "util/rsthreads.h"
|
|
||||||
#include "util/rsstring.h"
|
|
||||||
#include "util/rsprint.h"
|
|
||||||
|
|
||||||
#include "rsitems/rsitem.h"
|
|
||||||
#include "rsitems/itempriorities.h"
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
|
||||||
|
#include "serialiser/rsbaseserial.h"
|
||||||
|
#include "util/cxx23retrocompat.h"
|
||||||
|
#include "util/rsthreads.h"
|
||||||
|
#include "util/rsstring.h"
|
||||||
|
#include "util/rsprint.h"
|
||||||
|
#include "rsitems/rsitem.h"
|
||||||
|
#include "rsitems/itempriorities.h"
|
||||||
|
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* #define RSSERIAL_DEBUG 1
|
* #define RSSERIAL_DEBUG 1
|
||||||
|
@ -166,11 +167,17 @@ uint8_t RsItem::PacketSubType() const
|
||||||
/* For Service Packets */
|
/* For Service Packets */
|
||||||
RsItem::RsItem(uint8_t ver, uint16_t service, uint8_t subtype)
|
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
|
// This value triggers PQIInterface to complain about undefined priorities
|
||||||
|
_priority_level = QOS_PRIORITY_UNKNOWN;
|
||||||
type = (ver << 24) + (service << 8) + subtype;
|
type = (ver << 24) + (service << 8) + subtype;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RsItem::RsItem( uint8_t ver, RsServiceType service, uint8_t subtype,
|
||||||
|
RsItemPriority prio ):
|
||||||
|
type(static_cast<uint32_t>(
|
||||||
|
(ver << 24) + (std::to_underlying(service) << 8) + subtype )),
|
||||||
|
_priority_level(prio) {}
|
||||||
|
|
||||||
uint16_t RsItem::PacketService() const
|
uint16_t RsItem::PacketService() const
|
||||||
{
|
{
|
||||||
return (type >> 8) & 0xFFFF;
|
return (type >> 8) & 0xFFFF;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* RetroShare Broadcast Domain Discovery *
|
* RetroShare Broadcast Domain Discovery *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2019 Gioacchino Mazzurco <gio@altermundi.net> *
|
* Copyright (C) 2019-2021 Gioacchino Mazzurco <gio@altermundi.net> *
|
||||||
|
* Copyright (C) 2019-2021 Asociación Civil Altermundi <info@altermundi.net> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
@ -25,16 +26,17 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
|
||||||
# include <QtAndroid>
|
|
||||||
#endif // def __ANDROID__
|
|
||||||
|
|
||||||
#include "services/broadcastdiscoveryservice.h"
|
#include "services/broadcastdiscoveryservice.h"
|
||||||
#include "retroshare/rspeers.h"
|
#include "retroshare/rspeers.h"
|
||||||
#include "serialiser/rsserializable.h"
|
#include "serialiser/rsserializable.h"
|
||||||
#include "serialiser/rsserializer.h"
|
#include "serialiser/rsserializer.h"
|
||||||
#include "retroshare/rsevents.h"
|
#include "retroshare/rsevents.h"
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
# include "rs_android/retroshareserviceandroid.hpp"
|
||||||
|
#endif // def __ANDROID__
|
||||||
|
|
||||||
|
|
||||||
/*extern*/ RsBroadcastDiscovery* rsBroadcastDiscovery = nullptr;
|
/*extern*/ RsBroadcastDiscovery* rsBroadcastDiscovery = nullptr;
|
||||||
|
|
||||||
struct BroadcastDiscoveryPack : RsSerializable
|
struct BroadcastDiscoveryPack : RsSerializable
|
||||||
|
@ -99,7 +101,7 @@ BroadcastDiscoveryService::BroadcastDiscoveryService(
|
||||||
if(mRsPeers.isHiddenNode(mRsPeers.getOwnId())) return;
|
if(mRsPeers.isHiddenNode(mRsPeers.getOwnId())) return;
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
createMulticastLock();
|
createAndroidMulticastLock();
|
||||||
#endif // def __ANDROID__
|
#endif // def __ANDROID__
|
||||||
|
|
||||||
enableMulticastListening();
|
enableMulticastListening();
|
||||||
|
@ -228,19 +230,47 @@ RsBroadcastDiscoveryResult BroadcastDiscoveryService::createResult(
|
||||||
bool BroadcastDiscoveryService::isMulticastListeningEnabled()
|
bool BroadcastDiscoveryService::isMulticastListeningEnabled()
|
||||||
{
|
{
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
return assertMulticastLockIsvalid() &&
|
if(!mAndroidWifiMulticastLock)
|
||||||
mWifiMulticastLock.callMethod<jboolean>("isHeld");
|
{
|
||||||
#endif // def __ANDROID__
|
RS_ERR("Android multicast lock not initialized!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto uenv = jni::GetAttachedEnv(RsJni::getVM());
|
||||||
|
JNIEnv& env = *uenv;
|
||||||
|
auto& multicastLockClass = jni::Class<AndroidMulticastLock>::Singleton(env);
|
||||||
|
|
||||||
|
auto isHeld =
|
||||||
|
multicastLockClass.GetMethod<jni::jboolean()>(
|
||||||
|
env, "isHeld" );
|
||||||
|
|
||||||
|
return mAndroidWifiMulticastLock.Call(env, isHeld);
|
||||||
|
#else // def __ANDROID__
|
||||||
return true;
|
return true;
|
||||||
|
#endif // def __ANDROID__
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BroadcastDiscoveryService::enableMulticastListening()
|
bool BroadcastDiscoveryService::enableMulticastListening()
|
||||||
{
|
{
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
if(assertMulticastLockIsvalid() && !isMulticastListeningEnabled())
|
if(!mAndroidWifiMulticastLock)
|
||||||
{
|
{
|
||||||
mWifiMulticastLock.callMethod<void>("acquire");
|
RS_ERR("Android multicast lock not initialized!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!isMulticastListeningEnabled())
|
||||||
|
{
|
||||||
|
auto uenv = jni::GetAttachedEnv(RsJni::getVM());
|
||||||
|
JNIEnv& env = *uenv;
|
||||||
|
auto& multicastLockClass = jni::Class<AndroidMulticastLock>::Singleton(env);
|
||||||
|
|
||||||
|
auto acquire =
|
||||||
|
multicastLockClass.GetMethod<void()>(
|
||||||
|
env, "acquire" );
|
||||||
|
|
||||||
|
mAndroidWifiMulticastLock.Call(env, acquire);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif // def __ANDROID__
|
#endif // def __ANDROID__
|
||||||
|
@ -251,9 +281,24 @@ bool BroadcastDiscoveryService::enableMulticastListening()
|
||||||
bool BroadcastDiscoveryService::disableMulticastListening()
|
bool BroadcastDiscoveryService::disableMulticastListening()
|
||||||
{
|
{
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
if(assertMulticastLockIsvalid() && isMulticastListeningEnabled())
|
if(!mAndroidWifiMulticastLock)
|
||||||
{
|
{
|
||||||
mWifiMulticastLock.callMethod<void>("release");
|
RS_ERR("Android multicast lock not initialized!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isMulticastListeningEnabled())
|
||||||
|
{
|
||||||
|
auto uenv = jni::GetAttachedEnv(RsJni::getVM());
|
||||||
|
JNIEnv& env = *uenv;
|
||||||
|
auto& multicastLockClass = jni::Class<AndroidMulticastLock>::Singleton(env);
|
||||||
|
|
||||||
|
auto release =
|
||||||
|
multicastLockClass.GetMethod<void()>(
|
||||||
|
env, "release" );
|
||||||
|
|
||||||
|
mAndroidWifiMulticastLock.Call(env, release);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif // def __ANDROID__
|
#endif // def __ANDROID__
|
||||||
|
@ -262,56 +307,57 @@ bool BroadcastDiscoveryService::disableMulticastListening()
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
bool BroadcastDiscoveryService::createMulticastLock()
|
|
||||||
|
bool BroadcastDiscoveryService::createAndroidMulticastLock()
|
||||||
{
|
{
|
||||||
Dbg2() << __PRETTY_FUNCTION__ << std::endl;
|
if(mAndroidWifiMulticastLock)
|
||||||
|
|
||||||
constexpr auto fname = __PRETTY_FUNCTION__;
|
|
||||||
const auto failure = [&](const std::string& err)
|
|
||||||
{
|
{
|
||||||
RsErr() << fname << " " << err << std::endl;
|
RS_ERR("Android multicast lock is already initialized");
|
||||||
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<jstring>() );
|
|
||||||
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<jstring>() );
|
|
||||||
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();
|
print_stacktrace();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto uenv = jni::GetAttachedEnv(RsJni::getVM());
|
||||||
|
JNIEnv& env = *uenv;
|
||||||
|
|
||||||
|
using AContextTag = RetroShareServiceAndroid::Context;
|
||||||
|
using AContext = jni::Class<AContextTag>;
|
||||||
|
static auto& contextClass = AContext::Singleton(env);
|
||||||
|
|
||||||
|
auto wifiServiceField = jni::StaticField<AContextTag, jni::String>(
|
||||||
|
env, contextClass, "WIFI_SERVICE");
|
||||||
|
|
||||||
|
jni::Local<jni::String> WIFI_SERVICE = contextClass.Get(
|
||||||
|
env, wifiServiceField );
|
||||||
|
|
||||||
|
auto androidContext = RetroShareServiceAndroid::getAndroidContext(env);
|
||||||
|
|
||||||
|
auto getSystemService =
|
||||||
|
contextClass.GetMethod<jni::Object<jni::ObjectTag> (jni::String)>(
|
||||||
|
env, "getSystemService" );
|
||||||
|
|
||||||
|
struct WifiManager
|
||||||
|
{ static constexpr auto Name() { return "android/net/wifi/WifiManager"; } };
|
||||||
|
|
||||||
|
auto& wifiManagerClass = jni::Class<WifiManager>::Singleton(env);
|
||||||
|
|
||||||
|
auto wifiManager = jni::Cast<WifiManager>(
|
||||||
|
env, wifiManagerClass,
|
||||||
|
androidContext.Call(env, getSystemService, WIFI_SERVICE) );
|
||||||
|
|
||||||
|
auto createMulticastLock =
|
||||||
|
wifiManagerClass.GetMethod<jni::Object<AndroidMulticastLock>(jni::String)>(
|
||||||
|
env, "createMulticastLock" );
|
||||||
|
|
||||||
|
mAndroidWifiMulticastLock = jni::NewGlobal(
|
||||||
|
env, wifiManager.Call(
|
||||||
|
env, createMulticastLock,
|
||||||
|
jni::Make<jni::String>(
|
||||||
|
env, "RetroShare BroadcastDiscoveryService" ) ) );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // def __ANDROID__
|
#endif // def __ANDROID__
|
||||||
|
|
||||||
RsBroadcastDiscovery::~RsBroadcastDiscovery() = default;
|
RsBroadcastDiscovery::~RsBroadcastDiscovery() = default;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* RetroShare Broadcast Domain Discovery *
|
* RetroShare Broadcast Domain Discovery *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2019 Gioacchino Mazzurco <gio@altermundi.net> *
|
* Copyright (C) 2019-2021 Gioacchino Mazzurco <gio@altermundi.net> *
|
||||||
|
* Copyright (C) 2019-2021 Asociación Civil Altermundi <info@altermundi.net> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
@ -27,14 +28,16 @@
|
||||||
|
|
||||||
#include <udp_discovery_peer.hpp>
|
#include <udp_discovery_peer.hpp>
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
|
||||||
# include <QtAndroidExtras/QAndroidJniObject>
|
|
||||||
#endif // def __ANDROID__
|
|
||||||
|
|
||||||
#include "retroshare/rsbroadcastdiscovery.h"
|
#include "retroshare/rsbroadcastdiscovery.h"
|
||||||
#include "util/rsthreads.h"
|
#include "util/rsthreads.h"
|
||||||
#include "util/rsdebug.h"
|
#include "util/rsdebug.h"
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
# include <jni/jni.hpp>
|
||||||
|
# include "rs_android/rsjni.hpp"
|
||||||
|
#endif // def __ANDROID__
|
||||||
|
|
||||||
|
|
||||||
namespace UDC = udpdiscovery;
|
namespace UDC = udpdiscovery;
|
||||||
class RsPeers;
|
class RsPeers;
|
||||||
|
|
||||||
|
@ -42,7 +45,7 @@ class BroadcastDiscoveryService :
|
||||||
public RsBroadcastDiscovery, public RsTickingThread
|
public RsBroadcastDiscovery, public RsTickingThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BroadcastDiscoveryService(RsPeers& pRsPeers);
|
explicit BroadcastDiscoveryService(RsPeers& pRsPeers);
|
||||||
~BroadcastDiscoveryService() override;
|
~BroadcastDiscoveryService() override;
|
||||||
|
|
||||||
/// @see RsBroadcastDiscovery
|
/// @see RsBroadcastDiscovery
|
||||||
|
@ -71,26 +74,27 @@ protected:
|
||||||
std::map<UDC::IpPort, std::string> mDiscoveredData;
|
std::map<UDC::IpPort, std::string> mDiscoveredData;
|
||||||
RsMutex mDiscoveredDataMutex;
|
RsMutex mDiscoveredDataMutex;
|
||||||
|
|
||||||
RsPeers& mRsPeers; // TODO: std::shared_ptr<RsPeers> mRsPeers;
|
RsPeers& mRsPeers;
|
||||||
|
|
||||||
RsBroadcastDiscoveryResult createResult(
|
RsBroadcastDiscoveryResult createResult(
|
||||||
const UDC::IpPort& ipp, const std::string& uData );
|
const UDC::IpPort& ipp, const std::string& uData );
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
/** Android WifiManager.MulticastLock */
|
struct AndroidMulticastLock
|
||||||
QAndroidJniObject mWifiMulticastLock;
|
{
|
||||||
|
static constexpr auto Name()
|
||||||
|
{ return "android/net/wifi/WifiManager$MulticastLock"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
jni::Global<jni::Object<AndroidMulticastLock>> mAndroidWifiMulticastLock;
|
||||||
|
|
||||||
/** Initialize the wifi multicast lock without acquiring it
|
/** Initialize the wifi multicast lock without acquiring it
|
||||||
* Needed to enable multicast listening in Android, for RetroShare broadcast
|
* Needed to enable multicast listening in Android, for RetroShare broadcast
|
||||||
* discovery inspired by:
|
* discovery inspired by:
|
||||||
* https://github.com/flutter/flutter/issues/16335#issuecomment-420547860
|
* https://github.com/flutter/flutter/issues/16335#issuecomment-420547860
|
||||||
*/
|
*/
|
||||||
bool createMulticastLock();
|
bool createAndroidMulticastLock();
|
||||||
|
#endif
|
||||||
/** Return false if mWifiMulticastLock is invalid and print error messages */
|
|
||||||
bool assertMulticastLockIsvalid();
|
|
||||||
|
|
||||||
#endif // def __ANDROID__
|
|
||||||
|
|
||||||
RS_SET_CONTEXT_DEBUG_LEVEL(3)
|
RS_SET_CONTEXT_DEBUG_LEVEL(3)
|
||||||
};
|
};
|
||||||
|
|
|
@ -900,10 +900,19 @@ bool p3GxsForums::markRead(const RsGxsGrpMsgIdPair& msgId, bool read)
|
||||||
bool p3GxsForums::subscribeToForum(const RsGxsGroupId& groupId, bool subscribe )
|
bool p3GxsForums::subscribeToForum(const RsGxsGroupId& groupId, bool subscribe )
|
||||||
{
|
{
|
||||||
uint32_t token;
|
uint32_t token;
|
||||||
if( !RsGenExchange::subscribeToGroup(token, groupId, subscribe) || waitToken(token) != RsTokenService::COMPLETE ) return false;
|
if( !RsGenExchange::subscribeToGroup(token, groupId, subscribe) ||
|
||||||
|
waitToken(token) != RsTokenService::COMPLETE ) return false;
|
||||||
|
|
||||||
RsGxsGroupId grp;
|
RsGxsGroupId grp;
|
||||||
acknowledgeGrp(token,grp);
|
acknowledgeGrp(token, grp);
|
||||||
|
|
||||||
|
/* Since subscribe has been requested, the caller is most probably
|
||||||
|
* interested in getting the group messages ASAP so check updates from peers
|
||||||
|
* without waiting GXS sync timer.
|
||||||
|
* Do it here as this is meaningful or not depending on the service.
|
||||||
|
* Do it only after the token has been completed otherwise the pull have no
|
||||||
|
* effect. */
|
||||||
|
if(subscribe) RsGenExchange::netService()->checkUpdatesFromPeers();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1150,6 +1159,13 @@ std::error_condition p3GxsForums::setPostKeepForever(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::error_condition p3GxsForums::requestSynchronization()
|
||||||
|
{
|
||||||
|
auto errc = RsGenExchange::netService()->checkUpdatesFromPeers();
|
||||||
|
if(errc) return errc;
|
||||||
|
return RsGenExchange::netService()->requestPull();
|
||||||
|
}
|
||||||
|
|
||||||
/* so we need the same tick idea as wiki for generating dummy forums
|
/* so we need the same tick idea as wiki for generating dummy forums
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -175,6 +175,8 @@ public:
|
||||||
rs_owner_ptr<uint8_t>& resultData, uint32_t& resultSize ) override;
|
rs_owner_ptr<uint8_t>& resultData, uint32_t& resultSize ) override;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
std::error_condition requestSynchronization() override;
|
||||||
|
|
||||||
/// implementation of rsGxsGorums
|
/// implementation of rsGxsGorums
|
||||||
///
|
///
|
||||||
bool getGroupData(const uint32_t &token, std::vector<RsGxsForumGroup> &groups) override;
|
bool getGroupData(const uint32_t &token, std::vector<RsGxsForumGroup> &groups) override;
|
||||||
|
|
|
@ -1067,7 +1067,7 @@ bool p3IdService::createIdentity(uint32_t& token, RsIdentityParameters ¶ms)
|
||||||
|
|
||||||
if(params.isPgpLinked)
|
if(params.isPgpLinked)
|
||||||
{
|
{
|
||||||
ssdata.pgp.pgpId = AuthGPG::getAuthGPG()->getGPGOwnId();
|
ssdata.pgp.pgpId = AuthPGP::getPgpOwnId();
|
||||||
ssdata.pgp.lastCheckTs = time(nullptr);
|
ssdata.pgp.lastCheckTs = time(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3619,7 +3619,7 @@ RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup(
|
||||||
unsigned int sign_size = MAX_SIGN_SIZE;
|
unsigned int sign_size = MAX_SIGN_SIZE;
|
||||||
memset(signarray,0,MAX_SIGN_SIZE) ; // just in case.
|
memset(signarray,0,MAX_SIGN_SIZE) ; // just in case.
|
||||||
|
|
||||||
int result = AuthGPG::getAuthGPG()->SignDataBin(
|
int result = AuthPGP::SignDataBin(
|
||||||
static_cast<const void*>(hash.toByteArray()),
|
static_cast<const void*>(hash.toByteArray()),
|
||||||
hash.SIZE_IN_BYTES, signarray, &sign_size,
|
hash.SIZE_IN_BYTES, signarray, &sign_size,
|
||||||
__PRETTY_FUNCTION__ )
|
__PRETTY_FUNCTION__ )
|
||||||
|
@ -4096,7 +4096,7 @@ void p3IdService::getPgpIdList()
|
||||||
#endif // DEBUG_IDS
|
#endif // DEBUG_IDS
|
||||||
|
|
||||||
std::list<RsPgpId> list;
|
std::list<RsPgpId> list;
|
||||||
mPgpUtils->getGPGAllList(list);
|
mPgpUtils->getPgpAllList(list);
|
||||||
|
|
||||||
RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/
|
RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/
|
||||||
|
|
||||||
|
@ -4593,7 +4593,7 @@ void p3IdService::generateDummy_FriendPGP()
|
||||||
// Now Generate for friends.
|
// Now Generate for friends.
|
||||||
std::list<RsPgpId> gpgids;
|
std::list<RsPgpId> gpgids;
|
||||||
std::list<RsPgpId>::const_iterator it;
|
std::list<RsPgpId>::const_iterator it;
|
||||||
mPgpUtils->getGPGAllList(gpgids);
|
mPgpUtils->getPgpAllList(gpgids);
|
||||||
|
|
||||||
RsGxsIdGroup id;
|
RsGxsIdGroup id;
|
||||||
|
|
||||||
|
|
|
@ -111,11 +111,7 @@ PRE_TARGETDEPS += $$pretargetStaticLibs(sLibs)
|
||||||
LIBS += $$linkDynamicLibs(dLibs)
|
LIBS += $$linkDynamicLibs(dLibs)
|
||||||
|
|
||||||
android-* {
|
android-* {
|
||||||
## ifaddrs is missing on Android to add them don't use the one from
|
INCLUDEPATH *= $$clean_path($${RS_SRC_PATH}/supportlibs/jni.hpp/include/)
|
||||||
## https://github.com/morristech/android-ifaddrs
|
|
||||||
## because it crash, use QNetworkInterface from Qt instead
|
|
||||||
CONFIG *= qt
|
|
||||||
QT *= network
|
|
||||||
}
|
}
|
||||||
|
|
||||||
################################### Pkg-Config Stuff #############################
|
################################### Pkg-Config Stuff #############################
|
||||||
|
|
34
libretroshare/src/util/cxx23retrocompat.h
Normal file
34
libretroshare/src/util/cxx23retrocompat.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* RetroShare C++23 backwards compatibility utilities *
|
||||||
|
* *
|
||||||
|
* libretroshare: retroshare core library *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2021 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.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 <https://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
*******************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#if ! defined(__cpp_lib_to_underlying)
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
template <class Enum>
|
||||||
|
constexpr underlying_type_t<Enum> to_underlying(Enum e) noexcept
|
||||||
|
{ return static_cast<std::underlying_type_t<Enum>>(e); }
|
||||||
|
}
|
||||||
|
#endif // ! defined(__cpp_lib_to_underlying)
|
27
openpgpsdk/CMakeLists.txt
Normal file
27
openpgpsdk/CMakeLists.txt
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# RetroShare decentralized communication platform
|
||||||
|
#
|
||||||
|
# Copyright (C) 2021 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||||
|
# Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
cmake_minimum_required (VERSION 3.12.0)
|
||||||
|
project(openpgpsdk)
|
||||||
|
|
||||||
|
find_package(ZLIB REQUIRED)
|
||||||
|
find_package(BZip2 REQUIRED)
|
||||||
|
find_package(OpenSSL REQUIRED)
|
||||||
|
|
||||||
|
file(GLOB SOURCES src/openpgpsdk/*.c)
|
||||||
|
add_library(${PROJECT_NAME} ${SOURCES})
|
||||||
|
|
||||||
|
target_include_directories(
|
||||||
|
${PROJECT_NAME}
|
||||||
|
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||||
|
PRIVATE ${OPENSSL_INCLUDE_DIR}
|
||||||
|
PRIVATE ${BZIP2_INCLUDE_DIRS}
|
||||||
|
PRIVATE ${ZLIB_INCLUDE_DIRS} )
|
||||||
|
|
||||||
|
target_link_libraries(
|
||||||
|
${PROJECT_NAME}
|
||||||
|
OpenSSL::SSL OpenSSL::Crypto BZip2::BZip2 ZLIB::ZLIB )
|
|
@ -104,8 +104,8 @@ AudioWizard::AudioWizard(QWidget *p) : QWizard(p) {
|
||||||
iMaxPeak = 0;
|
iMaxPeak = 0;
|
||||||
iTicks = 0;
|
iTicks = 0;
|
||||||
|
|
||||||
qpTalkingOn = QPixmap::fromImage(QImage(QLatin1String("skin:talking_on.svg")).scaled(64,64));
|
qpTalkingOn = QPixmap::fromImage(QImage(QLatin1String(":/images/talking_on.svg")).scaled(64,64));
|
||||||
qpTalkingOff = QPixmap::fromImage(QImage(QLatin1String("skin:talking_off.svg")).scaled(64,64));
|
qpTalkingOff = QPixmap::fromImage(QImage(QLatin1String(":/images/talking_off.svg")).scaled(64,64));
|
||||||
|
|
||||||
bInit = false;
|
bInit = false;
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <QColorDialog>
|
#include <QColorDialog>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
|
#include <QInputDialog>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
#include <QStatusBar>
|
#include <QStatusBar>
|
||||||
|
@ -1689,3 +1690,19 @@ void MainWindow::setCompactStatusMode(bool compact)
|
||||||
ratesstatus->setCompactMode(compact);
|
ratesstatus->setCompactMode(compact);
|
||||||
//opModeStatus: TODO Show only ???
|
//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;
|
||||||
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#ifndef _MainWindow_H
|
#ifndef _MainWindow_H
|
||||||
#define _MainWindow_H
|
#define _MainWindow_H
|
||||||
|
|
||||||
|
#include <QLineEdit>
|
||||||
#include <QSystemTrayIcon>
|
#include <QSystemTrayIcon>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
@ -74,6 +75,14 @@ class MessengerWindow;
|
||||||
class ApplicationWindow;
|
class ApplicationWindow;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
struct Gui_InputDialogReturn
|
||||||
|
{
|
||||||
|
int execReturn;
|
||||||
|
QString textValue;
|
||||||
|
};
|
||||||
|
Q_DECLARE_METATYPE(Gui_InputDialogReturn);
|
||||||
|
|
||||||
class MainWindow : public RWindow
|
class MainWindow : public RWindow
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -210,9 +219,35 @@ public slots:
|
||||||
void showBandwidthGraph();
|
void showBandwidthGraph();
|
||||||
|
|
||||||
void toggleStatusToolTip(bool toggle);
|
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>("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:
|
protected:
|
||||||
/** Default Constructor */
|
/** Default Constructor */
|
||||||
MainWindow(QWidget *parent = 0, Qt::WindowFlags flags = 0);
|
MainWindow(QWidget *parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags());
|
||||||
|
|
||||||
void closeEvent(QCloseEvent *);
|
void closeEvent(QCloseEvent *);
|
||||||
|
|
||||||
|
|
|
@ -144,7 +144,7 @@ void BoardPostDisplayWidgetBase::readToggled()
|
||||||
emit changeReadStatusRequested(mPost.mMeta.mMsgId,s);
|
emit changeReadStatusRequested(mPost.mMeta.mMsgId,s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoardPostDisplayWidgetBase::setup()
|
void BoardPostDisplayWidgetBase::baseSetup()
|
||||||
{
|
{
|
||||||
// show/hide things based on the view type
|
// show/hide things based on the view type
|
||||||
|
|
||||||
|
@ -166,8 +166,6 @@ void BoardPostDisplayWidgetBase::setup()
|
||||||
QAction *CopyLinkAction = new QAction(QIcon(""),tr("Copy RetroShare Link"), this);
|
QAction *CopyLinkAction = new QAction(QIcon(""),tr("Copy RetroShare Link"), this);
|
||||||
connect(CopyLinkAction, SIGNAL(triggered()), this, SLOT(handleCopyLinkClicked()));
|
connect(CopyLinkAction, SIGNAL(triggered()), this, SLOT(handleCopyLinkClicked()));
|
||||||
|
|
||||||
int S = QFontMetricsF(font()).height() ;
|
|
||||||
|
|
||||||
readButton()->setChecked(false);
|
readButton()->setChecked(false);
|
||||||
|
|
||||||
QMenu *menu = new QMenu();
|
QMenu *menu = new QMenu();
|
||||||
|
@ -184,6 +182,7 @@ void BoardPostDisplayWidgetBase::setup()
|
||||||
if(redacted)
|
if(redacted)
|
||||||
{
|
{
|
||||||
commentButton()->setDisabled(true);
|
commentButton()->setDisabled(true);
|
||||||
|
shareButton()->setDisabled(true);
|
||||||
voteUpButton()->setDisabled(true);
|
voteUpButton()->setDisabled(true);
|
||||||
voteDownButton()->setDisabled(true);
|
voteDownButton()->setDisabled(true);
|
||||||
fromLabel()->setId(mPost.mMeta.mAuthorId);
|
fromLabel()->setId(mPost.mMeta.mAuthorId);
|
||||||
|
@ -196,8 +195,6 @@ void BoardPostDisplayWidgetBase::setup()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QPixmap sqpixmap2 = FilesDefs::getPixmapFromQtResourcePath(":/images/thumb-default.png");
|
|
||||||
|
|
||||||
QDateTime qtime;
|
QDateTime qtime;
|
||||||
qtime.setTime_t(mPost.mMeta.mPublishTs);
|
qtime.setTime_t(mPost.mMeta.mPublishTs);
|
||||||
QString timestamp = qtime.toString("hh:mm dd-MMM-yyyy");
|
QString timestamp = qtime.toString("hh:mm dd-MMM-yyyy");
|
||||||
|
@ -295,16 +292,7 @@ BoardPostDisplayWidget_compact::BoardPostDisplayWidget_compact(const RsPostedPos
|
||||||
: BoardPostDisplayWidgetBase(post,display_flags,parent), ui(new Ui::BoardPostDisplayWidget_compact())
|
: BoardPostDisplayWidgetBase(post,display_flags,parent), ui(new Ui::BoardPostDisplayWidget_compact())
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
setup();
|
BoardPostDisplayWidget_compact::setup();
|
||||||
|
|
||||||
ui->right_VL->addStretch();
|
|
||||||
ui->right_VL->setAlignment(Qt::AlignTop);
|
|
||||||
ui->topLayout->setAlignment(Qt::AlignTop);
|
|
||||||
ui->arrowsLayout->addStretch();
|
|
||||||
ui->arrowsLayout->setAlignment(Qt::AlignTop);
|
|
||||||
ui->feedFrame_VL->addStretch();
|
|
||||||
|
|
||||||
adjustSize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BoardPostDisplayWidget_compact::~BoardPostDisplayWidget_compact()
|
BoardPostDisplayWidget_compact::~BoardPostDisplayWidget_compact()
|
||||||
|
@ -314,7 +302,7 @@ BoardPostDisplayWidget_compact::~BoardPostDisplayWidget_compact()
|
||||||
|
|
||||||
void BoardPostDisplayWidget_compact::setup()
|
void BoardPostDisplayWidget_compact::setup()
|
||||||
{
|
{
|
||||||
BoardPostDisplayWidgetBase::setup();
|
baseSetup();
|
||||||
|
|
||||||
// show/hide things based on the view type
|
// show/hide things based on the view type
|
||||||
|
|
||||||
|
@ -356,7 +344,7 @@ void BoardPostDisplayWidget_compact::setup()
|
||||||
QObject::connect(ui->expandButton, SIGNAL(toggled(bool)), this, SLOT(doExpand(bool)));
|
QObject::connect(ui->expandButton, SIGNAL(toggled(bool)), this, SLOT(doExpand(bool)));
|
||||||
|
|
||||||
QTextDocument doc;
|
QTextDocument doc;
|
||||||
doc.setHtml(notes()->text());
|
doc.setHtml(BoardPostDisplayWidget_compact::notes()->text());
|
||||||
|
|
||||||
if(mDisplayFlags & SHOW_NOTES)
|
if(mDisplayFlags & SHOW_NOTES)
|
||||||
{
|
{
|
||||||
|
@ -427,16 +415,7 @@ BoardPostDisplayWidget_card::BoardPostDisplayWidget_card(const RsPostedPost& pos
|
||||||
: BoardPostDisplayWidgetBase(post,display_flags,parent), ui(new Ui::BoardPostDisplayWidget_card())
|
: BoardPostDisplayWidgetBase(post,display_flags,parent), ui(new Ui::BoardPostDisplayWidget_card())
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
setup();
|
BoardPostDisplayWidget_card::setup();
|
||||||
|
|
||||||
ui->right_VL->addStretch();
|
|
||||||
ui->right_VL->setAlignment(Qt::AlignTop);
|
|
||||||
ui->topLayout->setAlignment(Qt::AlignTop);
|
|
||||||
ui->arrowsLayout->addStretch();
|
|
||||||
ui->arrowsLayout->setAlignment(Qt::AlignTop);
|
|
||||||
ui->feedFrame_VL->addStretch();
|
|
||||||
|
|
||||||
adjustSize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BoardPostDisplayWidget_card::~BoardPostDisplayWidget_card()
|
BoardPostDisplayWidget_card::~BoardPostDisplayWidget_card()
|
||||||
|
@ -446,7 +425,7 @@ BoardPostDisplayWidget_card::~BoardPostDisplayWidget_card()
|
||||||
|
|
||||||
void BoardPostDisplayWidget_card::setup()
|
void BoardPostDisplayWidget_card::setup()
|
||||||
{
|
{
|
||||||
BoardPostDisplayWidgetBase::setup();
|
baseSetup();
|
||||||
|
|
||||||
RsReputationLevel overall_reputation = rsReputations->overallReputationLevel(mPost.mMeta.mAuthorId);
|
RsReputationLevel overall_reputation = rsReputations->overallReputationLevel(mPost.mMeta.mAuthorId);
|
||||||
bool redacted = (overall_reputation == RsReputationLevel::LOCALLY_NEGATIVE);
|
bool redacted = (overall_reputation == RsReputationLevel::LOCALLY_NEGATIVE);
|
||||||
|
@ -463,7 +442,6 @@ void BoardPostDisplayWidget_card::setup()
|
||||||
GxsIdDetails::loadPixmapFromData(mPost.mImage.mData, mPost.mImage.mSize, pixmap,GxsIdDetails::ORIGINAL);
|
GxsIdDetails::loadPixmapFromData(mPost.mImage.mData, mPost.mImage.mSize, pixmap,GxsIdDetails::ORIGINAL);
|
||||||
// Wiping data - as its been passed to thumbnail.
|
// Wiping data - as its been passed to thumbnail.
|
||||||
|
|
||||||
QPixmap scaledpixmap;
|
|
||||||
if(pixmap.width() > 800){
|
if(pixmap.width() > 800){
|
||||||
QPixmap scaledpixmap = pixmap.scaledToWidth(800, Qt::SmoothTransformation);
|
QPixmap scaledpixmap = pixmap.scaledToWidth(800, Qt::SmoothTransformation);
|
||||||
ui->pictureLabel->setPixmap(scaledpixmap);
|
ui->pictureLabel->setPixmap(scaledpixmap);
|
||||||
|
@ -478,10 +456,10 @@ void BoardPostDisplayWidget_card::setup()
|
||||||
}
|
}
|
||||||
|
|
||||||
QTextDocument doc;
|
QTextDocument doc;
|
||||||
doc.setHtml(notes()->text());
|
doc.setHtml(BoardPostDisplayWidget_card::notes()->text());
|
||||||
|
|
||||||
if(doc.toPlainText().trimmed().isEmpty())
|
if(doc.toPlainText().trimmed().isEmpty())
|
||||||
notes()->hide();
|
BoardPostDisplayWidget_card::notes()->hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
QToolButton *BoardPostDisplayWidget_card::voteUpButton() { return ui->voteUpButton; }
|
QToolButton *BoardPostDisplayWidget_card::voteUpButton() { return ui->voteUpButton; }
|
||||||
|
|
|
@ -62,10 +62,11 @@ public:
|
||||||
|
|
||||||
static const char *DEFAULT_BOARD_IMAGE;
|
static const char *DEFAULT_BOARD_IMAGE;
|
||||||
|
|
||||||
protected slots:
|
protected:
|
||||||
/* GxsGroupFeedItem */
|
/* 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 *voteUpButton() =0;
|
||||||
virtual QToolButton *commentButton() =0;
|
virtual QToolButton *commentButton() =0;
|
||||||
|
@ -81,6 +82,7 @@ protected slots:
|
||||||
virtual QToolButton *shareButton() =0;
|
virtual QToolButton *shareButton() =0;
|
||||||
virtual QFrame *feedFrame() =0;
|
virtual QFrame *feedFrame() =0;
|
||||||
|
|
||||||
|
protected slots:
|
||||||
void loadComments(bool e);
|
void loadComments(bool e);
|
||||||
void readToggled();
|
void readToggled();
|
||||||
void setReadStatus(bool isNew, bool isUnread) ;
|
void setReadStatus(bool isNew, bool isUnread) ;
|
||||||
|
|
|
@ -90,7 +90,10 @@
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QFrame" name="voteFrame">
|
<widget class="QFrame" name="voteFrame">
|
||||||
<layout class="QVBoxLayout" name="arrowsLayout">
|
<layout class="QVBoxLayout" name="voteFrame_VL">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
|
@ -173,6 +176,13 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="voteFrame_VS">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -277,7 +287,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="from_HSpacer">
|
<spacer name="from_HS">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -340,7 +350,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="pictureLabel_HSpacer">
|
<spacer name="pictureLabel_HS">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -401,16 +411,16 @@
|
||||||
<iconset resource="Posted_images.qrc">
|
<iconset resource="Posted_images.qrc">
|
||||||
<normaloff>:/images/share.png</normaloff>:/images/share.png</iconset>
|
<normaloff>:/images/share.png</normaloff>:/images/share.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="autoRaise">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="toolButtonStyle">
|
<property name="toolButtonStyle">
|
||||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="autoRaise">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="buttons_HSpacer">
|
<spacer name="buttons_HS">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -424,10 +434,30 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="right_VS">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="feedFrame_VS">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>542</width>
|
<width>542</width>
|
||||||
<height>150</height>
|
<height>151</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
@ -90,7 +90,22 @@
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QFrame" name="voteFrame">
|
<widget class="QFrame" name="voteFrame">
|
||||||
<layout class="QVBoxLayout" name="arrowsLayout">
|
<layout class="QVBoxLayout" name="voteFrame_VL">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QToolButton" name="voteUpButton">
|
<widget class="QToolButton" name="voteUpButton">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
@ -161,6 +176,13 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="voteFrame_VS">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -287,7 +309,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="from_HSpacer">
|
<spacer name="from_HS">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -305,7 +327,7 @@
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="buttons_HM">
|
<layout class="QHBoxLayout" name="buttons_HL">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QToolButton" name="commentButton">
|
<widget class="QToolButton" name="commentButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -400,7 +422,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="buttons_HSpacer">
|
<spacer name="buttons_HS">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -414,6 +436,13 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="right_VS">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -473,6 +502,13 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="feedFrame_VS">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>614</width>
|
<width>614</width>
|
||||||
<height>182</height>
|
<height>198</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
<property name="styleSheet">
|
<property name="styleSheet">
|
||||||
<string notr="true"/>
|
<string notr="true"/>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_3">
|
<layout class="QGridLayout" name="PostedCardView_GL">
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
|
@ -118,7 +118,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QHBoxLayout" name="from_HL">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>5</number>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
|
@ -216,7 +216,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer_4">
|
<spacer name="from_HS">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -241,30 +241,27 @@
|
||||||
<height>0</height>
|
<height>0</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="styleSheet">
|
|
||||||
<string notr="true"/>
|
|
||||||
</property>
|
|
||||||
<property name="frameShape">
|
<property name="frameShape">
|
||||||
<enum>QFrame::NoFrame</enum>
|
<enum>QFrame::NoFrame</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="frameShadow">
|
<property name="frameShadow">
|
||||||
<enum>QFrame::Plain</enum>
|
<enum>QFrame::Plain</enum>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="voteFrame_VL">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>3</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="topMargin">
|
<property name="topMargin">
|
||||||
<number>3</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="rightMargin">
|
<property name="rightMargin">
|
||||||
<number>3</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>3</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QToolButton" name="voteUpButton">
|
<widget class="QToolButton" name="voteUpButton">
|
||||||
|
@ -337,26 +334,20 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="voteFrame_VS">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizeType">
|
<property name="sizeType">
|
||||||
<enum>QSizePolicy::Expanding</enum>
|
<enum>QSizePolicy::Expanding</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>5</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="1">
|
<item row="5" column="1">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="buttons_HL">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QToolButton" name="commentButton">
|
<widget class="QToolButton" name="commentButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -389,7 +380,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer_3">
|
<spacer name="buttons_HS">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -461,7 +452,7 @@
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1">
|
<item row="4" column="1">
|
||||||
<widget class="QFrame" name="picture_frame">
|
<widget class="QFrame" name="picture_frame">
|
||||||
<layout class="QHBoxLayout" name="horizontalPictureLayout">
|
<layout class="QHBoxLayout" name="picture_frame_HL">
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
|
@ -485,7 +476,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer">
|
<spacer name="picture_frame_HS">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -513,9 +504,9 @@
|
||||||
</customwidget>
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../images.qrc"/>
|
|
||||||
<include location="../icons.qrc"/>
|
|
||||||
<include location="Posted_images.qrc"/>
|
<include location="Posted_images.qrc"/>
|
||||||
|
<include location="../icons.qrc"/>
|
||||||
|
<include location="../images.qrc"/>
|
||||||
</resources>
|
</resources>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
|
|
@ -41,9 +41,12 @@
|
||||||
#include "gui/common/FilesDefs.h"
|
#include "gui/common/FilesDefs.h"
|
||||||
|
|
||||||
/* View Page */
|
/* View Page */
|
||||||
#define VIEW_POST 1
|
#define VIEW_POST 0
|
||||||
#define VIEW_IMAGE 2
|
#define VIEW_IMAGE 1
|
||||||
#define VIEW_LINK 3
|
#define VIEW_LINK 2
|
||||||
|
/* View Image */
|
||||||
|
#define IMG_ATTACH 0
|
||||||
|
#define IMG_PICTURE 1
|
||||||
|
|
||||||
PostedCreatePostDialog::PostedCreatePostDialog(RsPosted *posted, const RsGxsGroupId& grpId, const RsGxsId& default_author, QWidget *parent):
|
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),
|
QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint),
|
||||||
|
@ -54,7 +57,6 @@ PostedCreatePostDialog::PostedCreatePostDialog(RsPosted *posted, const RsGxsGrou
|
||||||
Settings->loadWidgetInformation(this);
|
Settings->loadWidgetInformation(this);
|
||||||
|
|
||||||
connect(ui->postButton, SIGNAL(clicked()), this, SLOT(createPost()));
|
connect(ui->postButton, SIGNAL(clicked()), this, SLOT(createPost()));
|
||||||
connect(ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
|
||||||
connect(ui->addPicButton, SIGNAL(clicked() ), this , SLOT(addPicture()));
|
connect(ui->addPicButton, SIGNAL(clicked() ), this , SLOT(addPicture()));
|
||||||
connect(ui->RichTextEditWidget, SIGNAL(textSizeOk(bool)),ui->postButton, SLOT(setEnabled(bool)));
|
connect(ui->RichTextEditWidget, SIGNAL(textSizeOk(bool)),ui->postButton, SLOT(setEnabled(bool)));
|
||||||
|
|
||||||
|
@ -84,6 +86,7 @@ PostedCreatePostDialog::PostedCreatePostDialog(RsPosted *posted, const RsGxsGrou
|
||||||
connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(setPage(int)));
|
connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(setPage(int)));
|
||||||
|
|
||||||
ui->removeButton->hide();
|
ui->removeButton->hide();
|
||||||
|
ui->stackedWidgetPicture->setCurrentIndex(IMG_ATTACH);
|
||||||
|
|
||||||
/* load settings */
|
/* load settings */
|
||||||
processSettings(true);
|
processSettings(true);
|
||||||
|
@ -202,7 +205,6 @@ void PostedCreatePostDialog::addPicture()
|
||||||
|
|
||||||
// select a picture file
|
// select a picture file
|
||||||
if (misc::getOpenFileName(window(), RshareSettings::LASTDIR_IMAGES, tr("Load Picture File"), "Pictures (*.png *.xpm *.jpg *.jpeg *.gif *.webp )", imagefilename)) {
|
if (misc::getOpenFileName(window(), RshareSettings::LASTDIR_IMAGES, tr("Load Picture File"), "Pictures (*.png *.xpm *.jpg *.jpeg *.gif *.webp )", imagefilename)) {
|
||||||
QString encodedImage;
|
|
||||||
QImage image;
|
QImage image;
|
||||||
if (image.load(imagefilename) == false) {
|
if (image.load(imagefilename) == false) {
|
||||||
fprintf (stderr, "RsHtml::makeEmbeddedImage() - image \"%s\" can't be load\n", imagefilename.toLatin1().constData());
|
fprintf (stderr, "RsHtml::makeEmbeddedImage() - image \"%s\" can't be load\n", imagefilename.toLatin1().constData());
|
||||||
|
@ -213,7 +215,7 @@ void PostedCreatePostDialog::addPicture()
|
||||||
QImage opt;
|
QImage opt;
|
||||||
if(ImageUtil::optimizeSizeBytes(imagebytes, image, opt, 640*480, MAXMESSAGESIZE - 2000)) { //Leave space for other stuff
|
if(ImageUtil::optimizeSizeBytes(imagebytes, image, opt, 640*480, MAXMESSAGESIZE - 2000)) { //Leave space for other stuff
|
||||||
ui->imageLabel->setPixmap(QPixmap::fromImage(opt));
|
ui->imageLabel->setPixmap(QPixmap::fromImage(opt));
|
||||||
ui->stackedWidgetPicture->setCurrentIndex(1);
|
ui->stackedWidgetPicture->setCurrentIndex(IMG_PICTURE);
|
||||||
ui->removeButton->show();
|
ui->removeButton->show();
|
||||||
} else {
|
} else {
|
||||||
imagefilename = "";
|
imagefilename = "";
|
||||||
|
@ -259,45 +261,24 @@ int PostedCreatePostDialog::viewMode()
|
||||||
|
|
||||||
void PostedCreatePostDialog::setPage(int viewMode)
|
void PostedCreatePostDialog::setPage(int viewMode)
|
||||||
{
|
{
|
||||||
switch (viewMode) {
|
if( (viewMode < 0) || (viewMode > ui->stackedWidget->count()-1) )
|
||||||
case VIEW_POST:
|
viewMode = VIEW_POST;
|
||||||
ui->stackedWidget->setCurrentIndex(0);
|
|
||||||
|
|
||||||
ui->viewPostButton->setChecked(true);
|
ui->stackedWidget->setCurrentIndex(viewMode);
|
||||||
ui->viewImageButton->setChecked(false);
|
|
||||||
ui->viewLinkButton->setChecked(false);
|
|
||||||
|
|
||||||
break;
|
ui->viewPostButton ->setChecked(viewMode==VIEW_POST);
|
||||||
case VIEW_IMAGE:
|
ui->viewImageButton->setChecked(viewMode==VIEW_IMAGE);
|
||||||
ui->stackedWidget->setCurrentIndex(1);
|
ui->viewLinkButton ->setChecked(viewMode==VIEW_LINK);
|
||||||
|
|
||||||
ui->viewImageButton->setChecked(true);
|
|
||||||
ui->viewPostButton->setChecked(false);
|
|
||||||
ui->viewLinkButton->setChecked(false);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case VIEW_LINK:
|
|
||||||
ui->stackedWidget->setCurrentIndex(2);
|
|
||||||
|
|
||||||
ui->viewLinkButton->setChecked(true);
|
|
||||||
ui->viewPostButton->setChecked(false);
|
|
||||||
ui->viewImageButton->setChecked(false);
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
setPage(VIEW_POST);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PostedCreatePostDialog::on_removeButton_clicked()
|
void PostedCreatePostDialog::on_removeButton_clicked()
|
||||||
{
|
{
|
||||||
imagefilename = "";
|
imagefilename = "";
|
||||||
imagebytes.clear();
|
imagebytes.clear();
|
||||||
QPixmap empty;
|
ui->imageLabel->setPixmap(QPixmap());
|
||||||
ui->imageLabel->setPixmap(empty);
|
|
||||||
ui->removeButton->hide();
|
ui->removeButton->hide();
|
||||||
ui->stackedWidgetPicture->setCurrentIndex(0);
|
ui->stackedWidgetPicture->setCurrentIndex(IMG_ATTACH);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PostedCreatePostDialog::reject()
|
void PostedCreatePostDialog::reject()
|
||||||
|
|
|
@ -52,7 +52,7 @@ private slots:
|
||||||
void addPicture();
|
void addPicture();
|
||||||
void on_removeButton_clicked();
|
void on_removeButton_clicked();
|
||||||
void fileHashingFinished(QList<HashedFile> hashedFiles);
|
void fileHashingFinished(QList<HashedFile> hashedFiles);
|
||||||
void reject();
|
void reject() override; //QDialog
|
||||||
|
|
||||||
void setPage(int viewMode);
|
void setPage(int viewMode);
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -143,7 +143,7 @@
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="QStackedWidget" name="stackedWidgetPicture">
|
<widget class="QStackedWidget" name="stackedWidgetPicture">
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>1</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="PageAttach">
|
<widget class="QWidget" name="PageAttach">
|
||||||
<layout class="QGridLayout" name="PageAttach_GL">
|
<layout class="QGridLayout" name="PageAttach_GL">
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
<property name="styleSheet">
|
<property name="styleSheet">
|
||||||
<string notr="true"/>
|
<string notr="true"/>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_3">
|
<layout class="QGridLayout" name="PostedItem_GL">
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>1</number>
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
|
@ -82,21 +82,21 @@
|
||||||
<property name="frameShadow">
|
<property name="frameShadow">
|
||||||
<enum>QFrame::Plain</enum>
|
<enum>QFrame::Plain</enum>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="voteFrame_VL">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>3</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="topMargin">
|
<property name="topMargin">
|
||||||
<number>3</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="rightMargin">
|
<property name="rightMargin">
|
||||||
<number>3</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>3</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QToolButton" name="voteUpButton">
|
<widget class="QToolButton" name="voteUpButton">
|
||||||
|
@ -169,26 +169,20 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="voteFrame_VS">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizeType">
|
<property name="sizeType">
|
||||||
<enum>QSizePolicy::Expanding</enum>
|
<enum>QSizePolicy::Expanding</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>5</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1" rowspan="2">
|
<item row="0" column="1" rowspan="2">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
<layout class="QVBoxLayout" name="thumbnail_VL">
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>9</number>
|
<number>9</number>
|
||||||
</property>
|
</property>
|
||||||
|
@ -233,7 +227,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer_2">
|
<spacer name="thumbnail_VS">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -248,7 +242,7 @@
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="2">
|
<item row="0" column="2">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
<layout class="QVBoxLayout" name="title_VL">
|
||||||
<property name="topMargin">
|
<property name="topMargin">
|
||||||
<number>6</number>
|
<number>6</number>
|
||||||
</property>
|
</property>
|
||||||
|
@ -286,7 +280,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="newCommHLayout">
|
<layout class="QHBoxLayout" name="newComm_HL">
|
||||||
<property name="topMargin">
|
<property name="topMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
|
@ -312,7 +306,7 @@
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="2">
|
<item row="1" column="2">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
<layout class="QVBoxLayout" name="from_VL">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
|
@ -320,7 +314,7 @@
|
||||||
<enum>QLayout::SetDefaultConstraint</enum>
|
<enum>QLayout::SetDefaultConstraint</enum>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QHBoxLayout" name="from_HL">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>5</number>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
|
@ -416,7 +410,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer_4">
|
<spacer name="from_HS">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -434,7 +428,7 @@
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="buttonHLayout">
|
<layout class="QHBoxLayout" name="buttons_HL">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>6</number>
|
<number>6</number>
|
||||||
</property>
|
</property>
|
||||||
|
@ -567,7 +561,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer">
|
<spacer name="buttons_HS">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -631,9 +625,9 @@
|
||||||
<property name="frameShadow">
|
<property name="frameShadow">
|
||||||
<enum>QFrame::Raised</enum>
|
<enum>QFrame::Raised</enum>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="frame_picture_HL">
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer_2">
|
<spacer name="frame_picture_LHS">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -659,7 +653,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer_3">
|
<spacer name="frame_picture_RHS">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -685,7 +679,7 @@
|
||||||
<property name="frameShadow">
|
<property name="frameShadow">
|
||||||
<enum>QFrame::Sunken</enum>
|
<enum>QFrame::Sunken</enum>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="frame_notes_GL">
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>3</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
|
@ -726,17 +720,17 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>GxsIdLabel</class>
|
||||||
|
<extends>QLabel</extends>
|
||||||
|
<header>gui/gxs/GxsIdLabel.h</header>
|
||||||
|
</customwidget>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>ElidedLabel</class>
|
<class>ElidedLabel</class>
|
||||||
<extends>QLabel</extends>
|
<extends>QLabel</extends>
|
||||||
<header>gui/common/ElidedLabel.h</header>
|
<header>gui/common/ElidedLabel.h</header>
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
<customwidget>
|
|
||||||
<class>GxsIdLabel</class>
|
|
||||||
<extends>QLabel</extends>
|
|
||||||
<header>gui/gxs/GxsIdLabel.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>ClickableLabel</class>
|
<class>ClickableLabel</class>
|
||||||
<extends>QLabel</extends>
|
<extends>QLabel</extends>
|
||||||
|
|
|
@ -58,9 +58,7 @@
|
||||||
// number of posts to show at once.
|
// number of posts to show at once.
|
||||||
#define POSTS_CHUNK_SIZE 25
|
#define POSTS_CHUNK_SIZE 25
|
||||||
|
|
||||||
/****
|
//#define DEBUG_POSTED
|
||||||
* #define DEBUG_POSTED
|
|
||||||
***/
|
|
||||||
|
|
||||||
static const int POSTED_TABS_POSTS = 1;
|
static const int POSTED_TABS_POSTS = 1;
|
||||||
|
|
||||||
|
@ -87,6 +85,10 @@ 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
|
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,
|
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.
|
||||||
|
|
||||||
|
@ -98,7 +100,7 @@ void PostedPostDelegate::paint(QPainter * painter, const QStyleOptionViewItem &
|
||||||
|
|
||||||
painter->save();
|
painter->save();
|
||||||
|
|
||||||
painter->fillRect( option.rect, option.palette.background());
|
painter->fillRect( option.rect, option.palette.window());
|
||||||
painter->restore();
|
painter->restore();
|
||||||
|
|
||||||
QPixmap pixmap(option.rect.size());
|
QPixmap pixmap(option.rect.size());
|
||||||
|
@ -109,9 +111,9 @@ void PostedPostDelegate::paint(QPainter * painter, const QStyleOptionViewItem &
|
||||||
BoardPostDisplayWidget_compact w(post,displayFlags(post.mMeta.mMsgId),nullptr);
|
BoardPostDisplayWidget_compact w(post,displayFlags(post.mMeta.mMsgId),nullptr);
|
||||||
|
|
||||||
w.setFixedSize(option.rect.size());
|
w.setFixedSize(option.rect.size());
|
||||||
|
|
||||||
w.updateGeometry();
|
w.updateGeometry();
|
||||||
w.adjustSize();
|
w.adjustSize();
|
||||||
|
|
||||||
w.render(&pixmap,QPoint(0,0),QRegion(),QWidget::DrawChildren );// draw the widgets, not the background
|
w.render(&pixmap,QPoint(0,0),QRegion(),QWidget::DrawChildren );// draw the widgets, not the background
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -121,6 +123,7 @@ void PostedPostDelegate::paint(QPainter * painter, const QStyleOptionViewItem &
|
||||||
w.setFixedSize(option.rect.size());
|
w.setFixedSize(option.rect.size());
|
||||||
w.updateGeometry();
|
w.updateGeometry();
|
||||||
w.adjustSize();
|
w.adjustSize();
|
||||||
|
|
||||||
w.render(&pixmap,QPoint(0,0),QRegion(),QWidget::DrawChildren );// draw the widgets, not the background
|
w.render(&pixmap,QPoint(0,0),QRegion(),QWidget::DrawChildren );// draw the widgets, not the background
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,6 +148,10 @@ void PostedPostDelegate::paint(QPainter * painter, const QStyleOptionViewItem &
|
||||||
|
|
||||||
painter->save();
|
painter->save();
|
||||||
painter->drawPixmap(option.rect.topLeft(), pixmap /*,.scaled(option.rect.width(),option.rect.width()*w.height()/(float)w.width(),Qt::KeepAspectRatio,Qt::SmoothTransformation)*/);
|
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();
|
painter->restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,11 +200,19 @@ uint8_t PostedPostDelegate::displayFlags(const RsGxsMessageId &id) const
|
||||||
|
|
||||||
QWidget *PostedPostDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex& index) const
|
QWidget *PostedPostDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex& index) const
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (!index.isValid())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if(index.column() != RsPostedPostsModel::COLUMN_POSTS)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
QWidget *w ;
|
||||||
RsPostedPost post = index.data(Qt::UserRole).value<RsPostedPost>() ;
|
RsPostedPost post = index.data(Qt::UserRole).value<RsPostedPost>() ;
|
||||||
|
|
||||||
if(index.column() == RsPostedPostsModel::COLUMN_POSTS)
|
#ifdef DEBUG_POSTED
|
||||||
{
|
RS_DBG("Title:", post.mMeta.mMsgName.c_str());
|
||||||
QWidget *w ;
|
#endif
|
||||||
|
|
||||||
if(mDisplayMode==BoardPostDisplayWidget_compact::DISPLAY_MODE_COMPACT)
|
if(mDisplayMode==BoardPostDisplayWidget_compact::DISPLAY_MODE_COMPACT)
|
||||||
w = new BoardPostDisplayWidget_compact(post,displayFlags(post.mMeta.mMsgId),parent);
|
w = new BoardPostDisplayWidget_compact(post,displayFlags(post.mMeta.mMsgId),parent);
|
||||||
|
@ -206,27 +221,25 @@ QWidget *PostedPostDelegate::createEditor(QWidget *parent, const QStyleOptionVie
|
||||||
|
|
||||||
QObject::connect(w,SIGNAL(vote(RsGxsGrpMsgIdPair,bool)),mPostListWidget,SLOT(voteMsg(RsGxsGrpMsgIdPair,bool)));
|
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(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(commentsRequested(RsGxsMessageId,bool)),mPostListWidget,SLOT(openComments(RsGxsMessageId)));
|
||||||
QObject::connect(w,SIGNAL(changeReadStatusRequested(const RsGxsMessageId&,bool)),mPostListWidget,SLOT(changeReadStatus(const RsGxsMessageId&,bool)));
|
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.
|
// 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(thumbnailOpenned()),mPostListWidget,SLOT(markCurrentPostAsRead()));
|
||||||
QObject::connect(w,SIGNAL(vote(RsGxsGrpMsgIdPair,bool)),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(expand(RsGxsMessageId,bool)),this,SLOT(markCurrentPostAsRead()));
|
||||||
QObject::connect(w,SIGNAL(commentsRequested(const RsGxsMessageId&,bool)),mPostListWidget,SLOT(markCurrentPostAsRead()));
|
QObject::connect(w,SIGNAL(commentsRequested(RsGxsMessageId,bool)),mPostListWidget,SLOT(markCurrentPostAsRead()));
|
||||||
QObject::connect(w,SIGNAL(shareButtonClicked()),mPostListWidget,SLOT(markCurrentPostAsRead()));
|
QObject::connect(w,SIGNAL(shareButtonClicked()),mPostListWidget,SLOT(markCurrentPostAsRead()));
|
||||||
QObject::connect(w,SIGNAL(copylinkClicked()),mPostListWidget,SLOT(copyMessageLink()));
|
QObject::connect(w,SIGNAL(copylinkClicked()),mPostListWidget,SLOT(copyMessageLink()));
|
||||||
|
|
||||||
w->setFixedSize(option.rect.size());
|
w->setGeometry(option.rect);
|
||||||
w->adjustSize();
|
w->adjustSize();
|
||||||
w->updateGeometry();
|
w->updateGeometry();
|
||||||
w->adjustSize();
|
w->adjustSize();
|
||||||
|
|
||||||
return w;
|
return w;
|
||||||
}
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PostedPostDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
|
void PostedPostDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
|
||||||
{
|
{
|
||||||
editor->setGeometry(option.rect);
|
editor->setGeometry(option.rect);
|
||||||
|
@ -264,13 +277,11 @@ PostedListWidgetWithModel::PostedListWidgetWithModel(const RsGxsGroupId& postedI
|
||||||
connect(ui->nextButton,SIGNAL(clicked()),this,SLOT(nextPosts()));
|
connect(ui->nextButton,SIGNAL(clicked()),this,SLOT(nextPosts()));
|
||||||
connect(ui->prevButton,SIGNAL(clicked()),this,SLOT(prevPosts()));
|
connect(ui->prevButton,SIGNAL(clicked()),this,SLOT(prevPosts()));
|
||||||
|
|
||||||
connect(ui->postsTree,SIGNAL(customContextMenuRequested(const QPoint&)),this,SLOT(postContextMenu(const QPoint&)));
|
connect(ui->postsTree,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(postContextMenu(QPoint)));
|
||||||
connect(ui->viewModeButton,SIGNAL(clicked()),this,SLOT(switchDisplayMode()));
|
connect(ui->viewModeButton,SIGNAL(clicked()),this,SLOT(switchDisplayMode()));
|
||||||
|
|
||||||
connect(mPostedPostsModel,SIGNAL(boardPostsLoaded()),this,SLOT(postPostLoad()));
|
connect(mPostedPostsModel,SIGNAL(boardPostsLoaded()),this,SLOT(postPostLoad()));
|
||||||
|
|
||||||
QFontMetricsF fm(font());
|
|
||||||
|
|
||||||
/* Setup UI helper */
|
/* Setup UI helper */
|
||||||
|
|
||||||
/* Connect signals */
|
/* Connect signals */
|
||||||
|
@ -374,7 +385,6 @@ void PostedListWidgetWithModel::filterItems(QString text)
|
||||||
|
|
||||||
void PostedListWidgetWithModel::nextPosts()
|
void PostedListWidgetWithModel::nextPosts()
|
||||||
{
|
{
|
||||||
ui->postsTree->selectionModel()->clear();
|
|
||||||
if(mPostedPostsModel->displayedStartPostIndex() + POSTS_CHUNK_SIZE < mPostedPostsModel->filteredPostsCount())
|
if(mPostedPostsModel->displayedStartPostIndex() + POSTS_CHUNK_SIZE < mPostedPostsModel->filteredPostsCount())
|
||||||
{
|
{
|
||||||
mPostedPostsModel->setPostsInterval(POSTS_CHUNK_SIZE+mPostedPostsModel->displayedStartPostIndex(),POSTS_CHUNK_SIZE);
|
mPostedPostsModel->setPostsInterval(POSTS_CHUNK_SIZE+mPostedPostsModel->displayedStartPostIndex(),POSTS_CHUNK_SIZE);
|
||||||
|
@ -384,8 +394,6 @@ void PostedListWidgetWithModel::nextPosts()
|
||||||
|
|
||||||
void PostedListWidgetWithModel::prevPosts()
|
void PostedListWidgetWithModel::prevPosts()
|
||||||
{
|
{
|
||||||
ui->postsTree->selectionModel()->clear();
|
|
||||||
|
|
||||||
if((int)mPostedPostsModel->displayedStartPostIndex() > 0)
|
if((int)mPostedPostsModel->displayedStartPostIndex() > 0)
|
||||||
{
|
{
|
||||||
mPostedPostsModel->setPostsInterval((int)mPostedPostsModel->displayedStartPostIndex()-POSTS_CHUNK_SIZE,POSTS_CHUNK_SIZE);
|
mPostedPostsModel->setPostsInterval((int)mPostedPostsModel->displayedStartPostIndex()-POSTS_CHUNK_SIZE,POSTS_CHUNK_SIZE);
|
||||||
|
@ -490,8 +498,8 @@ void PostedListWidgetWithModel::handleEvent_main_thread(std::shared_ptr<const Rs
|
||||||
|
|
||||||
switch(e->mPostedEventCode)
|
switch(e->mPostedEventCode)
|
||||||
{
|
{
|
||||||
case RsPostedEventCode::NEW_COMMENT: // [[fallthrough]];
|
case RsPostedEventCode::NEW_COMMENT: [[fallthrough]];
|
||||||
case RsPostedEventCode::NEW_VOTE: // [[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
|
// special treatment here because the message might be a comment, so we need to refresh the comment tab if openned
|
||||||
|
|
||||||
|
@ -503,11 +511,12 @@ void PostedListWidgetWithModel::handleEvent_main_thread(std::shared_ptr<const Rs
|
||||||
t->refresh();
|
t->refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case RsPostedEventCode::NEW_MESSAGE: // [[fallthrough]];
|
[[clang::fallthrough]];
|
||||||
case RsPostedEventCode::NEW_POSTED_GROUP: // [[fallthrough]];
|
case RsPostedEventCode::NEW_MESSAGE: [[fallthrough]];
|
||||||
case RsPostedEventCode::UPDATED_POSTED_GROUP: // [[fallthrough]];
|
case RsPostedEventCode::NEW_POSTED_GROUP: [[fallthrough]];
|
||||||
case RsPostedEventCode::UPDATED_MESSAGE:
|
case RsPostedEventCode::UPDATED_POSTED_GROUP: [[fallthrough]];
|
||||||
case RsPostedEventCode::BOARD_DELETED:
|
case RsPostedEventCode::UPDATED_MESSAGE: [[fallthrough]];
|
||||||
|
case RsPostedEventCode::BOARD_DELETED: [[fallthrough]];
|
||||||
case RsPostedEventCode::SYNC_PARAMETERS_UPDATED:
|
case RsPostedEventCode::SYNC_PARAMETERS_UPDATED:
|
||||||
{
|
{
|
||||||
if(e->mPostedGroupId == groupId())
|
if(e->mPostedGroupId == groupId())
|
||||||
|
|
|
@ -251,7 +251,7 @@ p, li { white-space: pre-wrap; }
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizeType">
|
<property name="sizeType">
|
||||||
<enum>QSizePolicy::Preferred</enum>
|
<enum>QSizePolicy::Expanding</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizeHint" stdset="0">
|
<property name="sizeHint" stdset="0">
|
||||||
<size>
|
<size>
|
||||||
|
@ -310,7 +310,7 @@ p, li { white-space: pre-wrap; }
|
||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<pointsize>11</pointsize>
|
<pointsize>25</pointsize>
|
||||||
<weight>75</weight>
|
<weight>75</weight>
|
||||||
<italic>true</italic>
|
<italic>true</italic>
|
||||||
<bold>true</bold>
|
<bold>true</bold>
|
||||||
|
|
|
@ -381,7 +381,7 @@ void ChatWidget::init(const ChatId &chat_id, const QString &title)
|
||||||
hist_chat_type = RS_HISTORY_TYPE_PUBLIC;
|
hist_chat_type = RS_HISTORY_TYPE_PUBLIC;
|
||||||
messageCount = Settings->getPublicChatHistoryCount();
|
messageCount = Settings->getPublicChatHistoryCount();
|
||||||
|
|
||||||
ui->titleBarFrame->setVisible(false);
|
ui->headerBFrame->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rsHistory->getEnable(hist_chat_type))
|
if (rsHistory->getEnable(hist_chat_type))
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
<enum>QLayout::SetMaximumSize</enum>
|
<enum>QLayout::SetMaximumSize</enum>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QFrame" name="titleBarFrame">
|
<widget class="QFrame" name="headerBFrame">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>0</width>
|
<width>0</width>
|
||||||
|
@ -51,7 +51,7 @@
|
||||||
<property name="frameShadow">
|
<property name="frameShadow">
|
||||||
<enum>QFrame::Plain</enum>
|
<enum>QFrame::Plain</enum>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QHBoxLayout" name="titleBarFrameHLayout">
|
<layout class="QHBoxLayout" name="headerBFrameHLayout">
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>2</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
|
|
|
@ -18,20 +18,26 @@
|
||||||
* *
|
* *
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QResizeEvent>
|
|
||||||
#include "RSTreeView.h"
|
#include "RSTreeView.h"
|
||||||
|
|
||||||
RSTreeView::RSTreeView(QWidget *parent) : QTreeView(parent)
|
#include "util/rsdebug.h"
|
||||||
|
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QResizeEvent>
|
||||||
|
|
||||||
|
//#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)
|
void RSTreeView::wheelEvent(QWheelEvent *e)
|
||||||
{
|
{
|
||||||
if(e->modifiers() == Qt::ControlModifier)
|
if(e->modifiers() == Qt::ControlModifier)
|
||||||
{
|
{
|
||||||
emit zoomRequested(e->delta() > 0);
|
emit zoomRequested(e->angleDelta().y() > 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -40,20 +46,45 @@ void RSTreeView::wheelEvent(QWheelEvent *e)
|
||||||
|
|
||||||
void RSTreeView::mouseMoveEvent(QMouseEvent *e)
|
void RSTreeView::mouseMoveEvent(QMouseEvent *e)
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG_RSTREEVIEW
|
||||||
|
RS_DBG(e->localPos().x(), ":", e->localPos().y());
|
||||||
|
#endif
|
||||||
|
if (autoSelect)
|
||||||
|
{
|
||||||
QModelIndex idx = indexAt(e->pos());
|
QModelIndex idx = indexAt(e->pos());
|
||||||
|
|
||||||
if(idx.isValid() && idx != selectionModel()->currentIndex())
|
if(idx.isValid() && idx != selectionModel()->currentIndex())
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_RSTREEVIEW
|
||||||
|
RS_DBG("Selection changed");
|
||||||
|
#endif
|
||||||
selectionModel()->setCurrentIndex(idx,QItemSelectionModel::ClearAndSelect);
|
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)
|
void RSTreeView::setAutoSelect(bool b)
|
||||||
{
|
{
|
||||||
if(b)
|
autoSelect = b; // Keep this because setMouseTracking can be called outside.
|
||||||
setMouseTracking(true);
|
setMouseTracking(b);
|
||||||
else
|
|
||||||
setMouseTracking(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RSTreeView::resizeEvent(QResizeEvent *e)
|
void RSTreeView::resizeEvent(QResizeEvent *e)
|
||||||
|
|
|
@ -29,13 +29,19 @@ class RSTreeView : public QTreeView
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RSTreeView(QWidget *parent = 0);
|
RSTreeView(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief set Placeholder Text
|
||||||
|
* @param text
|
||||||
|
*/
|
||||||
void setPlaceholderText(const QString &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
|
* @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);
|
void setAutoSelect(bool b);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -44,11 +50,13 @@ signals:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void mouseMoveEvent(QMouseEvent *e) override; // overriding so as to manage auto-selection
|
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 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;
|
virtual void paintEvent(QPaintEvent *event) override;
|
||||||
|
|
||||||
QString placeholderText;
|
QString placeholderText;
|
||||||
|
bool autoSelect;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "ConnectFriendWizard.h"
|
#include "ConnectFriendWizard.h"
|
||||||
#include "ui_ConnectFriendWizard.h"
|
#include "ui_ConnectFriendWizard.h"
|
||||||
#include "gui/common/PeerDefs.h"
|
#include "gui/common/PeerDefs.h"
|
||||||
|
#include "gui/connect/ConfCertDialog.h"
|
||||||
#include "gui/notifyqt.h"
|
#include "gui/notifyqt.h"
|
||||||
#include "gui/common/GroupDefs.h"
|
#include "gui/common/GroupDefs.h"
|
||||||
#include "gui/msgs/MessageComposer.h"
|
#include "gui/msgs/MessageComposer.h"
|
||||||
|
@ -572,6 +573,16 @@ void ConnectFriendWizard::initializePage(int id)
|
||||||
ui->ipEdit->setText(s);
|
ui->ipEdit->setText(s);
|
||||||
ui->signersEdit->setPlainText(ts);
|
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);
|
fillGroups(this, ui->groupComboBox, groupId);
|
||||||
|
|
||||||
if(peerDetails.isHiddenNode)
|
if(peerDetails.isHiddenNode)
|
||||||
|
@ -587,6 +598,7 @@ void ConnectFriendWizard::initializePage(int id)
|
||||||
}
|
}
|
||||||
if(mIsShortInvite)
|
if(mIsShortInvite)
|
||||||
{
|
{
|
||||||
|
if(ui->nameEdit->text().isEmpty())
|
||||||
ui->nameEdit->setText(tr("[Unknown]"));
|
ui->nameEdit->setText(tr("[Unknown]"));
|
||||||
ui->addKeyToKeyring_CB->setChecked(false);
|
ui->addKeyToKeyring_CB->setChecked(false);
|
||||||
ui->addKeyToKeyring_CB->setEnabled(false);
|
ui->addKeyToKeyring_CB->setEnabled(false);
|
||||||
|
@ -856,19 +868,19 @@ void ConnectFriendWizard::cleanFriendCert()
|
||||||
{
|
{
|
||||||
bool certValid = false;
|
bool certValid = false;
|
||||||
QString errorMsg ;
|
QString errorMsg ;
|
||||||
|
QString certDetail;
|
||||||
std::string cert = ui->friendCertEdit->toPlainText().toUtf8().constData();
|
std::string cert = ui->friendCertEdit->toPlainText().toUtf8().constData();
|
||||||
|
|
||||||
if (cert.empty()) {
|
if (cert.empty()) {
|
||||||
ui->friendCertCleanLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/delete.png"));
|
|
||||||
ui->friendCertCleanLabel->setToolTip("");
|
ui->friendCertCleanLabel->setToolTip("");
|
||||||
ui->friendCertCleanLabel->setStyleSheet("");
|
|
||||||
errorMsg = tr("");
|
errorMsg = tr("");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
std::string cleanCert;
|
std::string cleanCert;
|
||||||
uint32_t error_code;
|
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;
|
certValid = true;
|
||||||
|
|
||||||
|
@ -879,7 +891,7 @@ void ConnectFriendWizard::cleanFriendCert()
|
||||||
whileBlocking(ui->friendCertEdit)->setPlainText(QString::fromUtf8(cleanCert.c_str()));
|
whileBlocking(ui->friendCertEdit)->setPlainText(QString::fromUtf8(cleanCert.c_str()));
|
||||||
whileBlocking(ui->friendCertEdit)->setTextCursor(textCursor);
|
whileBlocking(ui->friendCertEdit)->setTextCursor(textCursor);
|
||||||
|
|
||||||
ui->friendCertCleanLabel->setStyleSheet("");
|
certDetail = ConfCertDialog::getCertificateDescription(details,false,mIsShortInvite,!details.ipAddressList.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mIsShortInvite)
|
if (mIsShortInvite)
|
||||||
|
@ -903,16 +915,17 @@ void ConnectFriendWizard::cleanFriendCert()
|
||||||
|
|
||||||
default:
|
default:
|
||||||
errorMsg = tr("Not a valid Retroshare certificate!") ;
|
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->setPixmap(certValid ? FilesDefs::getPixmapFromQtResourcePath(":/images/accepted16.png") : FilesDefs::getPixmapFromQtResourcePath(":/images/delete.png"));
|
||||||
ui->friendCertCleanLabel->setToolTip(errorMsg);
|
ui->friendCertCleanLabel->setToolTip("<p>" + errorMsg + (certValid ? "\n" + certDetail : "") + "</p>");
|
||||||
ui->friendCertCleanLabel->setText(errorMsg);
|
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);
|
ui->TextPage->setComplete(certValid);
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue