Merge pull request #550 from G10h4ck/android

Android - Still need to remove all refs to Qt.
This commit is contained in:
Cyril Soler 2016-11-07 20:55:02 +01:00 committed by GitHub
commit befeb44f07
74 changed files with 2944 additions and 205 deletions

4
.gitignore vendored
View File

@ -1,4 +1,3 @@
/RetroShare.pro.user
*.o
*.sw?
*.so
@ -10,3 +9,6 @@ Makefile*
*.sw?
*~
Thumbs.db
*.pro.user
.kdev4
*.kdev4

View File

@ -47,12 +47,12 @@ addons:
project:
name: "RetroShare/RetroShare"
description: "RetroShare Build submitted via Travis CI"
build_command_prepend: "qmake CONFIG+=NO_SQLCIPHER; make clean"
build_command_prepend: "qmake CONFIG+=no_sqlcipher; make clean"
build_command: "make -j 4"
branch_pattern: coverity_scan
before_script:
- qmake QMAKE_CC=$CC QMAKE_CXX=$CXX CONFIG+=NO_SQLCIPHER CONFIG+=tests
- qmake QMAKE_CC=$CC QMAKE_CXX=$CXX CONFIG+=no_sqlcipher CONFIG+=tests
script:
- if [ $TRAVIS_OS_NAME == linux ] && [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then make && tests/unittests/unittests >/dev/null 2>&1 ; fi

86
README-Android.asciidoc Normal file
View File

@ -0,0 +1,86 @@
Compile Retroshare for Android
==============================
== Introduction
Compiling an application for Android is not as easy as one would imagine, expecially one like RetroShare that has a big codebase and is not well documented. This document is aimed to empower the reader so she can hopefully succed or at least have a significant help in compiling her own RetroShare APK package installable on Android.
== Preparing The Environement
First of all setup your Qt for Android development environement following the guide on the link:http://doc.qt.io/qt-5/androidgs.html[Qt for android web site].
At this point you should have Android SDK, Android NDK, and Qt for Android working fine, and you should be capable of executing on an Android emulator or on your Android phone Qt for Android examples.
But RetroShare is not as simple to compile as those examples. In particular, the Android NDK precompiled toolchain is limited and doesn't support the full C++ specification, and it is missing some part that is needed to build RetroShare. The good news is that Android NDK ships all the necessary to build a custom toolchain that is suitable to build RetroShare. In order to build the toolchain with needed library RetroShare provides the +android-prepare-toolchain.sh+ script; before you execute it you should define some variables the script cannot determine in an easy and reliable manner by itself in your terminal.
[source,bash]
-------------------------------------------------------------------------------
## The path where Android NDK is installed in your system
export ANDROID_NDK_PATH="/opt/android-ndk/"
## The path where your fresh compiled toolchain will be installed, make sure
## the parent exists
export NDK_TOOLCHAIN_PATH="/home/$(whoami)/Development/android-toolchains/retroshare-android/"
## The CPU architecture of the Android device you want to target
export ANDROID_NDK_ARCH="arm"
## The Android API level the Android device you want to target
export ANDROID_PLATFORM_VER="19"
## The number of core that yout host CPU have (just to speed up compilation) set it to 1 if unsure
export HOST_NUM_CPU=1
./android-prepare-toolchain.sh
-------------------------------------------------------------------------------
Now is time for the bad news: as of today Qt assumes you use the NDK precompiled toolchain and doesn't have an option to use the custom toolchain you just generated, so you need to tweak Qt internals a little to make usage of the custom toolchain. First of all you need to determine your Qt for Android installation path -in my case it is +/opt/Qt5.7.0/+ - then find the +mkspecs+ directory -in my case it is +/opt/Qt5.7.0/5.7/android_armv7/mkspecs+ - and then modify qmake configuration for the android target according to your toolchain, in my case I have done it with the following commands (in the same shell I used before, to take advantage of the already set variables):
WARNING: This may need a slight modification if you have a different Qt version.
[source,bash]
-------------------------------------------------------------------------------
export QT_PATH="/opt/Qt5.7.0/"
export QT_MAJOR_VERSION="5.7"
cd ${QT_PATH}/${QT_MAJOR_VERSION}/android_armv7/mkspecs
sudo --preserve-env -s
cp -r android-g++ android-g++-backup
cd android-g++
sed -i "s|^NDK_TOOLCHAIN_PATH =.*|NDK_TOOLCHAIN_PATH = ${NDK_TOOLCHAIN_PATH}|" qmake.conf
-------------------------------------------------------------------------------
== Preparing Qt Creator
Now that your environement is set up you should configure Qt Creator for Android following the link:http://doc.qt.io/qtcreator/creator-developing-android.html[official guide]. At the end of this step your Qt Creator should recognize the Android compiler and the Qt for Android kit. As we use a custom toolchain one more step is needed.
From the top menu click
_Tools -> Options... -> Build & Run -> Compilers -> Android GCC (arm-4.9) -> Clone_
Now a new compiler (usually named +Clone of Android GCC (arm-4.9)+) should have appeared on your compilers list. Select that compiler and press the Browse button to look for your custom toolchain compiler. You should find it at +$NDK_TOOLCHAIN_PATH/bin/arm-linux-androideabi-gcc+. Select it, then press Apply.
Now go to the Kits tab, select +Android for armeabi-v7a (GCC 4.9, Qt 5.7.0)+ and press the Clone button. A new kit is created (usually named +Clone of Android for armeabi-v7a (GCC 4.9, Qt 5.7.0)+). Now select the new kit and change the compiler to the one you have just created.
Your Kit is now ready to use. Now you can open RetroShare as a Qt Creator project and in the Projects left menu add the newly created kit if not already present, so you can select it on the build type selection button down on the left.
Some of RetroShare modules like +retroshare-gui+, +WebUI+ and +sqlcipher+ are not supported yet on Android so to be able to compile RetroShare without errors you will have to go to +
_Qt Creator left pane -> Projects -> Build and Run -> Android SOMESTUFF kit -> Build Steps -> qmake -> Additional arguments_
and add the following configurations
[source,makefile]
-------------------------------------------------------------------------------
CONFIG+=no_retroshare_gui CONFIG+=no_retroshare_nogui CONFIG+=no_retroshare_plugins CONFIG+=retroshare_android_service CONFIG+=libresapilocalserver CONFIG+=no_libresapihttpserver CONFIG+=no_sqlcipher CONFIG+=retroshare_qml_app
-------------------------------------------------------------------------------
WARNING: SQLCipher is not supported yet on RetroShare for Android. This poses a major security concern, we are working to fix this ASAP.
WARNING: Some versions of QtCreator try to find the Android SDK in +/opt/android/sdk+. A workaround to this is to make a symbolic link there pointing to your SDK installation path, like +mkdir -p /opt/android/sdk && ln -s /home/user/android-sdk-linux /opt/android/sdk+
== Furter Readings
- link:http://doc.qt.io/qt-5/android-support.html[]
- link:https://developer.android.com/ndk/guides/libs.html[]
- link:retroshare://forum?name=Compiling%20nogui%20for%20android&id=8fd22bd8f99754461e7ba1ca8a727995&msgid=4e0f92330600bba9cf978f384f4b7b2f2ca64eff[]
- link:retroshare://file?name=Android%20Native%20Development%20Kit%20Cookbook.pdf&size=29214468&hash=0123361c1b14366ce36118e82b90faf7c7b1b136[]

View File

@ -3,36 +3,54 @@
TEMPLATE = subdirs
#CONFIG += tests
SUBDIRS += \
openpgpsdk \
libbitdht \
libretroshare \
libresapi \
retroshare_gui \
retroshare_nogui \
plugins
SUBDIRS += openpgpsdk
openpgpsdk.file = openpgpsdk/src/openpgpsdk.pro
SUBDIRS += libbitdht
libbitdht.file = libbitdht/src/libbitdht.pro
SUBDIRS += libretroshare
libretroshare.file = libretroshare/src/libretroshare.pro
libretroshare.depends = openpgpsdk libbitdht
SUBDIRS += libresapi
libresapi.file = libresapi/src/libresapi.pro
libresapi.depends = libretroshare
retroshare_gui.file = retroshare-gui/src/retroshare-gui.pro
retroshare_gui.depends = libretroshare libresapi
retroshare_gui.target = retroshare-gui
retroshare_gui {
SUBDIRS += retroshare_gui
retroshare_gui.file = retroshare-gui/src/retroshare-gui.pro
retroshare_gui.depends = libretroshare libresapi
retroshare_gui.target = retroshare_gui
}
retroshare_nogui.file = retroshare-nogui/src/retroshare-nogui.pro
retroshare_nogui.depends = libretroshare libresapi
retroshare_nogui.target = retroshare-nogui
retroshare_nogui {
SUBDIRS += retroshare_nogui
retroshare_nogui.file = retroshare-nogui/src/retroshare-nogui.pro
retroshare_nogui.depends = libretroshare libresapi
retroshare_nogui.target = retroshare_nogui
}
plugins.file = plugins/plugins.pro
plugins.depends = retroshare_gui
plugins.target = plugins
retroshare_android_service {
SUBDIRS += retroshare_android_service
retroshare_android_service.file = retroshare-android-service/src/retroshare-android-service.pro
retroshare_android_service.depends = libretroshare libresapi
retroshare_android_service.target = retroshare_android_service
}
retroshare_qml_app {
SUBDIRS += retroshare_qml_app
retroshare_qml_app.file = retroshare-qml-app/src/retroshare-qml-app.pro
retroshare_qml_app.depends = libretroshare retroshare_android_service
retroshare_qml_app.target = retroshare_qml_app
}
retroshare_plugins {
SUBDIRS += plugins
plugins.file = plugins/plugins.pro
plugins.depends = retroshare_gui
plugins.target = plugins
}
wikipoos {
SUBDIRS += pegmarkdown

152
android-prepare-toolchain.sh Executable file
View File

@ -0,0 +1,152 @@
#!/bin/bash
## You are supposed to provide the following variables according to your system setup
[ -z ${ANDROID_NDK_PATH+x} ] && export ANDROID_NDK_PATH="/opt/android-ndk/"
[ -z ${ANDROID_NDK_ARCH+x} ] && export ANDROID_NDK_ARCH="arm"
[ -z ${ANDROID_NDK_ABI_VER+x} ] && export ANDROID_NDK_ABI_VER="4.9"
[ -z ${ANDROID_PLATFORM_VER+x} ] && export ANDROID_PLATFORM_VER="18"
[ -z ${NDK_TOOLCHAIN_PATH+x} ] && export NDK_TOOLCHAIN_PATH="/home/$(whoami)/Development/android-toolchains/retroshare-android-${ANDROID_PLATFORM_VER}-${ANDROID_NDK_ARCH}-abi${ANDROID_NDK_ABI_VER}/"
[ -z ${HOST_NUM_CPU+x} ] && export HOST_NUM_CPU=4
runDir="$(pwd)"
## You should not edit the following variables
if [ "${ANDROID_NDK_ARCH}" == "x86" ]; then
cArch="i686"
eABI=""
else
cArch="${ANDROID_NDK_ARCH}"
eABI="eabi"
fi
export SYSROOT="${NDK_TOOLCHAIN_PATH}/sysroot"
export PREFIX="${SYSROOT}"
export CC="${NDK_TOOLCHAIN_PATH}/bin/${cArch}-linux-android${eABI}-gcc"
export CXX="${NDK_TOOLCHAIN_PATH}/bin/${cArch}-linux-android${eABI}-g++"
export AR="${NDK_TOOLCHAIN_PATH}/bin/${cArch}-linux-android${eABI}-ar"
export RANLIB="${NDK_TOOLCHAIN_PATH}/bin/${cArch}-linux-android${eABI}-ranlib"
export ANDROID_DEV="${ANDROID_NDK_PATH}/platforms/android-${ANDROID_PLATFORM_VER}/arch-${ANDROID_NDK_ARCH}/usr"
## More information available at https://android.googlesource.com/platform/ndk/+/ics-mr0/docs/STANDALONE-TOOLCHAIN.html
build_toolchain()
{
rm -rf ${NDK_TOOLCHAIN_PATH}
[ "${ANDROID_NDK_ARCH}" == "x86" ] && toolchainName="${ANDROID_NDK_ARCH}-${ANDROID_NDK_ABI_VER}" || toolchainName="${ANDROID_NDK_ARCH}-linux-androideabi-${ANDROID_NDK_ABI_VER}"
${ANDROID_NDK_PATH}/build/tools/make-standalone-toolchain.sh --ndk-dir=${ANDROID_NDK_PATH} --arch=${ANDROID_NDK_ARCH} --install-dir=${NDK_TOOLCHAIN_PATH} --platform=android-${ANDROID_PLATFORM_VER} --toolchain=${toolchainName} --verbose
}
## More information available at retroshare://file?name=Android%20Native%20Development%20Kit%20Cookbook.pdf&size=29214468&hash=0123361c1b14366ce36118e82b90faf7c7b1b136
build_bzlib()
{
B_dir="bzip2-1.0.6"
rm -rf $B_dir
[ -f $B_dir.tar.gz ] || wget http://www.bzip.org/1.0.6/bzip2-1.0.6.tar.gz
tar -xf $B_dir.tar.gz
cd $B_dir
sed -i "/^CC=.*/d" Makefile
sed -i "/^AR=.*/d" Makefile
sed -i "/^RANLIB=.*/d" Makefile
sed -i "/^LDFLAGS=.*/d" Makefile
sed -i "s/^all: libbz2.a bzip2 bzip2recover test/all: libbz2.a bzip2 bzip2recover/" Makefile
make -j${HOST_NUM_CPU}
make install PREFIX=${SYSROOT}/usr
# sed -i "/^CC=.*/d" Makefile-libbz2_so
# make -f Makefile-libbz2_so -j${HOST_NUM_CPU}
# cp libbz2.so.1.0.6 ${SYSROOT}/usr/lib/libbz2.so
cd ..
}
## More information available at http://doc.qt.io/qt-5/opensslsupport.html
build_openssl()
{
B_dir="openssl-1.0.2h"
rm -rf $B_dir
[ -f $B_dir.tar.gz ] || wget https://www.openssl.org/source/$B_dir.tar.gz
tar -xf $B_dir.tar.gz
cd $B_dir
if [ "${ANDROID_NDK_ARCH}" == "arm" ]; then
oArch="armv7"
else
oArch="${ANDROID_NDK_ARCH}"
fi
# ANDROID_NDK_ROOT="${ANDROID_NDK_PATH}" ./Configure android-${oArch} shared --prefix="${SYSROOT}/usr" --openssldir="${SYSROOT}/etc/ssl"
## We link openssl statically to avoid android silently sneaking in his own
## version of libssl.so (we noticed this because it had some missing symbol
## that made RS crash), the crash in some android version is only one of the
## possible problems the fact that android insert his own binary libssl.so pose
## non neglegible security concerns.
ANDROID_NDK_ROOT="${ANDROID_NDK_PATH}" ./Configure android-${oArch} --prefix="${SYSROOT}/usr" --openssldir="${SYSROOT}/etc/ssl"
sed -i 's/LIBNAME=$$i LIBVERSION=$(SHLIB_MAJOR).$(SHLIB_MINOR) \\/LIBNAME=$$i \\/g' Makefile
sed -i '/LIBCOMPATVERSIONS=";$(SHLIB_VERSION_HISTORY)" \\/d' Makefile
make -j${HOST_NUM_CPU}
make install
# cp *.so "${SYSROOT}/usr/lib"
cd ..
}
build_sqlite()
{
B_dir="sqlite-autoconf-3130000"
[ -f $B_dir.tar.gz ] || wget https://www.sqlite.org/2016/$B_dir.tar.gz
tar -xf $B_dir.tar.gz
cd $B_dir
./configure --prefix="${SYSROOT}/usr" --host=${ANDROID_NDK_ARCH}-linux
make -j${HOST_NUM_CPU}
make install
rm -f ${SYSROOT}/usr/lib/libsqlite3.so*
${CC} -shared -o libsqlite3.so -fPIC sqlite3.o -ldl
cp libsqlite3.so "${SYSROOT}/usr/lib"
cd ..
}
build_sqlcipher()
{
echo "sqlcipher not supported yet on android"
return 0
cd sqlcipher
./configure --enable-tempstore=yes CFLAGS="-DSQLITE_HAS_CODEC" LDFLAGS="${SYSROOT}/usr/lib/libcrypto.a"
make -j${HOST_NUM_CPU}
make install
cd ..
}
build_libupnp()
{
B_dir="libupnp-1.6.20"
rm -rf $B_dir
[ -f $B_dir.tar.bz2 ] || wget https://sourceforge.net/projects/pupnp/files/pupnp/libUPnP%201.6.20/$B_dir.tar.bz2
tar -xf $B_dir.tar.bz2
cd $B_dir
## liupnp must be configured as static library because if not the linker will
## look for libthreadutils.so.6 at runtime that cannot be packaged on android
## as it supports only libname.so format for libraries, thus resulting in a
## crash at startup.
./configure --enable-static --disable-shared --disable-samples --prefix="${SYSROOT}/usr" --host=${ANDROID_NDK_ARCH}-linux
make -j${HOST_NUM_CPU}
make install
cd ..
}
build_libmicrohttpd()
{
echo "libmicrohttpd not supported yet on android"
return 0
B_dir="libmicrohttpd-0.9.50"
rm -rf $B_dir
[ -f $B_dir.tar.gz ] || wget ftp://ftp.gnu.org/gnu/libmicrohttpd/$B_dir.tar.gz
tar -xf $B_dir.tar.gz
cd $B_dir
./configure --prefix="${SYSROOT}/usr" --host=${ANDROID_NDK_ARCH}-linux
#make -e ?
make -j${HOST_NUM_CPU}
make install
cd ..
}
build_toolchain
build_bzlib
build_openssl
build_sqlite
build_libupnp

View File

@ -21,9 +21,9 @@
namespace resource_api{
ApiServerLocal::ApiServerLocal(ApiServer* server, QObject *parent) :
ApiServerLocal::ApiServerLocal(ApiServer* server, const QString &listenPath, QObject *parent) :
QObject(parent), serverThread(this),
localListener(server) // Must have no parent to be movable to other thread
localListener(server, listenPath) // Must have no parent to be movable to other thread
{
localListener.moveToThread(&serverThread);
serverThread.start();
@ -31,15 +31,17 @@ ApiServerLocal::ApiServerLocal(ApiServer* server, QObject *parent) :
ApiServerLocal::~ApiServerLocal() { serverThread.quit(); }
ApiLocalListener::ApiLocalListener(ApiServer *server, QObject *parent) :
ApiLocalListener::ApiLocalListener(ApiServer *server,
const QString &listenPath,
QObject *parent) :
QObject(parent), mApiServer(server), mLocalServer(this)
{
mLocalServer.removeServer(serverName());
mLocalServer.removeServer(listenPath);
#if QT_VERSION >= 0x050000
mLocalServer.setSocketOptions(QLocalServer::UserAccessOption);
#endif
connect(&mLocalServer, SIGNAL(newConnection()), this, SLOT(handleConnection()));
mLocalServer.listen(serverName());
mLocalServer.listen(listenPath);
}
void ApiLocalListener::handleConnection()
@ -71,16 +73,27 @@ void ApiLocalConnectionHandler::handlePendingRequests()
{
if(mLocalSocket->canReadLine())
{
readPath:
reqPath = mLocalSocket->readLine().constData();
mState = WAITING_DATA;
readPath:
QString rString(mLocalSocket->readLine());
rString = rString.simplified();
if (!rString.isEmpty())
{
if(rString.startsWith("PUT", Qt::CaseInsensitive)) reqMeth = resource_api::Request::PUT;
else if (rString.startsWith("DELETE", Qt::CaseInsensitive)) reqMeth = resource_api::Request::DELETE_AA;
else reqMeth = resource_api::Request::GET;
if(rString.contains(' ')) rString = rString.split(' ')[1];
/* Because QLocalSocket is SOCK_STREAM some clients implementations
* like the one based on QLocalSocket feel free to send the whole
* request (PATH + DATA) in a single write(), causing readyRead()
* signal being emitted only once, in that case we should continue
* processing without waiting for readyRead() being fired again, so
* we don't break here as there may be more lines to read */
reqPath = rString.toStdString();
mState = WAITING_DATA;
/* Because QLocalSocket is SOCK_STREAM some clients implementations
* like the one based on QLocalSocket feel free to send the whole
* request (PATH + DATA) in a single write(), causing readyRead()
* signal being emitted only once, in that case we should continue
* processing without waiting for readyRead() being fired again, so
* we don't break here as there may be more lines to read */
}
else break;
}
}
case WAITING_DATA:
@ -90,6 +103,7 @@ void ApiLocalConnectionHandler::handlePendingRequests()
resource_api::JsonStream reqJson;
reqJson.setJsonString(std::string(mLocalSocket->readLine().constData()));
resource_api::Request req(reqJson);
req.mMethod = reqMeth;
req.setPath(reqPath);
std::string resultString = mApiServer->handleRequest(req);
mLocalSocket->write(resultString.c_str(), resultString.length());

View File

@ -24,6 +24,7 @@
#include <retroshare/rsinit.h>
#include <string>
#include "ApiTypes.h"
#include "ApiServer.h"
namespace resource_api
@ -34,16 +35,9 @@ class ApiLocalListener : public QObject
Q_OBJECT
public:
ApiLocalListener(ApiServer* server, QObject *parent=0);
ApiLocalListener(ApiServer* server, const QString &listenPath, QObject *parent=0);
~ApiLocalListener() { mLocalServer.close(); }
const static QString& serverName()
{
const static QString sockPath(RsAccounts::AccountDirectory()
.append("/libresapi.sock").c_str());
return sockPath;
}
public slots:
void handleConnection();
@ -57,9 +51,23 @@ class ApiServerLocal : public QObject
Q_OBJECT
public:
ApiServerLocal(ApiServer* server, QObject *parent=0);
ApiServerLocal(ApiServer* server, const QString& listenPath, QObject *parent=0);
~ApiServerLocal();
const static QString& loginServerPath()
{
const static QString sockPath(RsAccounts::ConfigDirectory()
.append("/libresapi.sock").c_str());
return sockPath;
}
const static QString& serverPath()
{
const static QString sockPath(RsAccounts::AccountDirectory()
.append("/libresapi.sock").c_str());
return sockPath;
}
private:
QThread serverThread;
ApiLocalListener localListener;
@ -82,6 +90,7 @@ private:
QLocalSocket* mLocalSocket;
State mState;
std::string reqPath;
resource_api::Request::Method reqMeth;
};
} // namespace resource_api

View File

@ -211,30 +211,7 @@ public:
req.mMethod = resource_api::Request::DELETE_AA;
}
std::stack<std::string> stack;
std::string str;
for(std::string::reverse_iterator sit = path2.rbegin(); sit != path2.rend(); sit++)
{
if((*sit) != '/')
{
// add to front because we are traveling in reverse order
str = *sit + str;
}
else
{
if(str != "")
{
stack.push(str);
str.clear();
}
}
}
if(str != "")
{
stack.push(str);
}
req.mPath = stack;
req.mFullPath = path2;
req.setPath(path2);
std::string result = mApiServer->handleRequest(req);

View File

@ -193,29 +193,21 @@ public:
// then each handler should pop the top element
std::stack<std::string> mPath;
std::string mFullPath;
bool setPath(std::string reqPath)
bool setPath(const std::string &reqPath)
{
std::string str;
for(std::string::reverse_iterator sit = reqPath.rbegin(); sit != reqPath.rend(); sit++)
std::string::const_reverse_iterator sit;
for( sit = reqPath.rbegin(); sit != reqPath.rend(); ++sit )
{
if((*sit) != '/')
// add to front because we are traveling in reverse order
if((*sit) != '/') str = *sit + str;
else if(!str.empty())
{
// add to front because we are traveling in reverse order
str = *sit + str;
}
else
{
if(str != "")
{
mPath.push(str);
str.clear();
}
mPath.push(str);
str.clear();
}
}
if(str != "")
{
mPath.push(str);
}
if(!str.empty()) mPath.push(str);
mFullPath = reqPath;
return true;
@ -231,8 +223,7 @@ public:
// contains data for new resources
StreamBase& mStream;
// use the is*() methods to query the method type
//private:
// use the is*() methods to query the method type:
enum Method { GET, PUT, DELETE_AA, EXEC};// something is wrong with DELETE, it won't compile with it
Method mMethod;
};

View File

@ -59,7 +59,7 @@ bool RsControlModule::askForPassword(const std::string &title, const std::string
{
cancelled = false ;
{
RsStackMutex stack(mDataMtx); // ********** LOCKED **********
RS_STACK_MUTEX(mDataMtx); // ********** LOCKED **********
if(mFixedPassword != "")
{
password = mFixedPassword;
@ -78,7 +78,7 @@ bool RsControlModule::askForPassword(const std::string &title, const std::string
{
usleep(5*1000);
RsStackMutex stack(mDataMtx); // ********** LOCKED **********
RS_STACK_MUTEX(mDataMtx); // ********** LOCKED **********
wait = mWantPassword;
if(!wait && mPassword != "")
{

View File

@ -243,7 +243,10 @@ bool GxsSecurity::checkPublicKey(const RsTlvPublicRSAKey &key)
bool GxsSecurity::generateKeyPair(RsTlvPublicRSAKey& public_key,RsTlvPrivateRSAKey& private_key)
{
// admin keys
RSA *rsa = RSA_generate_key(2048, 65537, NULL, NULL);
BIGNUM *ebn = BN_new();
BN_set_word(ebn, 65537);
RSA *rsa = RSA_new();
RSA_generate_key_ex(rsa, 2048, ebn, NULL);
RSA *rsa_pub = RSAPublicKey_dup(rsa);
public_key.keyFlags = RSTLV_KEY_TYPE_PUBLIC_ONLY ;

View File

@ -156,8 +156,7 @@ linux-* {
QMAKE_CXXFLAGS *= -Wall -D_FILE_OFFSET_BITS=64
QMAKE_CC = $${QMAKE_CXX}
contains(CONFIG, NO_SQLCIPHER) {
DEFINES *= NO_SQLCIPHER
no_sqlcipher {
PKGCONFIG *= sqlite3
} else {
SQLCIPHER_OK = $$system(pkg-config --exists sqlcipher && echo yes)
@ -168,7 +167,7 @@ linux-* {
DEPENDPATH += ../../../lib/
INCLUDEPATH += ../../../lib/
} else {
error("libsqlcipher is not installed and libsqlcipher.a not found. SQLCIPHER is necessary for encrypted database, to build with unencrypted database, run: qmake CONFIG+=NO_SQLCIPHER")
error("libsqlcipher is not installed and libsqlcipher.a not found. SQLCIPHER is necessary for encrypted database, to build with unencrypted database, run: qmake CONFIG+=no_sqlcipher")
}
} else {
# Workaround for broken sqlcipher packages, e.g. Ubuntu 14.04
@ -182,7 +181,7 @@ linux-* {
# linux/bsd can use either - libupnp is more complete and packaged.
#CONFIG += upnp_miniupnpc
CONFIG += upnp_libupnp
CONFIG += upnp_libupnp
# Check if the systems libupnp has been Debian-patched
system(grep -E 'char[[:space:]]+PublisherUrl' /usr/include/upnp/upnp.h >/dev/null 2>&1) {
@ -332,7 +331,7 @@ freebsd-* {
# linux/bsd can use either - libupnp is more complete and packaged.
#CONFIG += upnp_miniupnpc
CONFIG += upnp_libupnp
CONFIG += upnp_libupnp
}
################################# OpenBSD ##########################################
@ -891,3 +890,25 @@ test_bitdht {
# ENABLED UDP NOW.
}
################################# Android #####################################
android-g++ {
## ifaddrs is missing on Android add them don't use the one from
## https://github.com/morristech/android-ifaddrs
## because they crash, use QNetworkInterface from Qt instead
CONFIG *= qt
QT *= network
## Add this here and not in retroshare.pri because static library are very
## sensible to order in command line, has to be in the end of file for the
## same reason
LIBS += -L$$NDK_TOOLCHAIN_PATH/sysroot/usr/lib/ -lssl
INCLUDEPATH += $$NDK_TOOLCHAIN_PATH/sysroot/usr/include
DEPENDPATH += $$NDK_TOOLCHAIN_PATH/sysroot/usr/include
PRE_TARGETDEPS += $$NDK_TOOLCHAIN_PATH/sysroot/usr/lib/libssl.a
LIBS += -L$$NDK_TOOLCHAIN_PATH/sysroot/usr/lib/ -lcrypto
INCLUDEPATH += $$NDK_TOOLCHAIN_PATH/sysroot/usr/include
DEPENDPATH += $$NDK_TOOLCHAIN_PATH/sysroot/usr/include
PRE_TARGETDEPS += $$NDK_TOOLCHAIN_PATH/sysroot/usr/lib/libcrypto.a
}

View File

@ -24,9 +24,9 @@
*/
#ifdef WINDOWS_SYS
#include "util/rswin.h"
#include "util/rsmemory.h"
#include <ws2tcpip.h>
# include "util/rswin.h"
# include "util/rsmemory.h"
# include <ws2tcpip.h>
#endif // WINDOWS_SYS
#include "pqi/pqinetwork.h"
@ -271,12 +271,17 @@ int inet_aton(const char *name, struct in_addr *addr)
#include <sys/types.h>
#ifdef WINDOWS_SYS
#include <winsock2.h>
#include <iphlpapi.h>
#pragma comment(lib, "IPHLPAPI.lib")
#else // WINDOWS_SYS
#include <ifaddrs.h>
#include <net/if.h>
# include <winsock2.h>
# include <iphlpapi.h>
# pragma comment(lib, "IPHLPAPI.lib")
#elif defined(__ANDROID__)
# include <string>
# include <QString>
# include <QHostAddress>
# include <QNetworkInterface>
#else // not __ANDROID__ nor WINDOWS => Linux and other unixes
# include <ifaddrs.h>
# include <net/if.h>
#endif // WINDOWS_SYS
bool getLocalAddresses(std::list<sockaddr_storage> & addrs)
@ -317,7 +322,15 @@ bool getLocalAddresses(std::list<sockaddr_storage> & addrs)
}
}
free(adapter_addresses);
#else // WINDOWS_SYS
#elif defined(__ANDROID__)
foreach(QHostAddress qAddr, QNetworkInterface::allAddresses())
{
sockaddr_storage tmpAddr;
sockaddr_storage_clear(tmpAddr);
if(sockaddr_storage_ipv4_aton(tmpAddr, qAddr.toString().toStdString().c_str()))
addrs.push_back(tmpAddr);
}
#else // not WINDOWS_SYS not ANDROID => Linux and other unixes
struct ifaddrs *ifsaddrs, *ifa;
if(getifaddrs(&ifsaddrs) != 0)
{

View File

@ -105,11 +105,15 @@ X509_REQ *GenerateX509Req(
fprintf(stderr,"GenerateX509Req: reverting to %d\n", nbits);
}
rsa = RSA_generate_key(nbits, e, NULL, NULL);
rsa = RSA_new();
if ((rsa == NULL) || !EVP_PKEY_assign_RSA(pkey, rsa))
throw std::runtime_error("Couldn't generate RSA Key");
BIGNUM *ebn = BN_new();
BN_set_word(ebn, e);
RSA_generate_key_ex(rsa, nbits, ebn, NULL);
// open the file.
FILE *out;
if (NULL == (out = RsDirUtil::rs_fopen(pkey_file.c_str(), "w")))

View File

@ -129,15 +129,21 @@ class RsInit
namespace RsAccounts
{
// Directories.
std::string ConfigDirectory(); // aka Base Directory. (normally ~/.retroshare)
/**
* @brief ConfigDirectory (normally ~/.retroshare) you can call this method
* even before initialisation (you can't with some other methods)
* @see RsAccountsDetail::PathBaseDirectory()
*/
std::string ConfigDirectory();
/**
* @brief DataDirectory
* you can call this method even before initialisation (you can't with the other methods)
* you can call this method even before initialisation (you can't with some other methods)
* @param check if set to true and directory does not exist, return empty string
* @return path where global platform independent files are stored, like bdboot.txt or webinterface files
*/
std::string DataDirectory(bool check = true);
std::string PGPDirectory();
std::string AccountDirectory();

View File

@ -26,11 +26,12 @@
*
*/
#include <sys/socket.h>
#include "retroshare/rspeers.h"
class p3LinkMgr;
class p3PeerMgr;
class p3NetMgr;
struct sockaddr_storage;
class p3Peers: public RsPeers

View File

@ -65,14 +65,8 @@ AccountDetails::AccountDetails()
return;
}
RsAccountsDetail::RsAccountsDetail()
:mAccountsLocked(false), mPreferredId(""), mBaseDirectory("")
{
mAccounts.clear();
mUnsupportedKeys.clear();
return;
}
RsAccountsDetail::RsAccountsDetail() : mAccountsLocked(false), mPreferredId("")
{}
bool RsAccountsDetail::loadAccounts()
{
@ -214,6 +208,7 @@ std::string RsAccountsDetail::PathPGPDirectory()
std::string RsAccountsDetail::PathBaseDirectory()
{
if(mBaseDirectory.empty()) defaultBaseDirectory();
return mBaseDirectory;
}
@ -326,8 +321,6 @@ bool RsAccountsDetail::setupBaseDirectory(std::string alt_basedir)
}
bool RsAccountsDetail::defaultBaseDirectory()
{
std::string basedir;
@ -339,8 +332,8 @@ bool RsAccountsDetail::defaultBaseDirectory()
char *h = getenv("HOME");
if (h == NULL)
{
std::cerr << "defaultBaseDirectory() Error: ";
std::cerr << "cannot determine $HOME dir" <<std::endl;
std::cerr << "defaultBaseDirectory() Error: cannot determine $HOME dir"
<< std::endl;
return false ;
}
@ -1253,7 +1246,7 @@ bool RsInit::LoadPassword(const std::string& id, const std::string& inPwd)
********************************************************************************/
// Directories.
std::string RsAccounts::ConfigDirectory() { return rsAccounts->PathBaseDirectory(); }
std::string RsAccounts::ConfigDirectory() { return RsAccountsDetail::PathBaseDirectory(); }
std::string RsAccounts::DataDirectory(bool check) { return RsAccountsDetail::PathDataDirectory(check); }
std::string RsAccounts::PGPDirectory() { return rsAccounts->PathPGPDirectory(); }
std::string RsAccounts::AccountDirectory() { return rsAccounts->PathAccountDirectory(); }
@ -1332,3 +1325,4 @@ bool RsAccounts::GenerateSSLCertificate(const RsPgpId& pgp_id, const std::str
* END OF: PUBLIC INTERFACE FUNCTIONS
********************************************************************************/
std::string RsAccountsDetail::mBaseDirectory;

View File

@ -80,7 +80,13 @@ class RsAccountsDetail
* @return path where global platform independent files are stored, like bdboot.txt or webinterface files
*/
static std::string PathDataDirectory(bool check = true);
std::string PathBaseDirectory();
/**
* @brief PathBaseDirectory
* @return path where user data is stored ( on Linux and similar
* systems it is usually something like /home/USERNAME/.retroshare ).
*/
static std::string PathBaseDirectory();
// PGP Path is only dependent on BaseDirectory.
std::string PathPGPDirectory();
@ -134,7 +140,7 @@ class RsAccountsDetail
private:
bool checkPreferredId();
bool defaultBaseDirectory();
static bool defaultBaseDirectory();
bool getAvailableAccounts(std::map<RsPeerId, AccountDetails> &accounts,
int& failing_accounts,
@ -148,7 +154,7 @@ class RsAccountsDetail
std::map<RsPeerId, AccountDetails> mAccounts;
RsPeerId mPreferredId;
std::string mBaseDirectory;
static std::string mBaseDirectory;
std::map<std::string,std::vector<std::string> > mUnsupportedKeys ;
};

View File

@ -508,7 +508,7 @@ int RsInit::InitRetroShare(int argcIgnored, char **argvIgnored, bool strictCheck
AuthSSL::AuthSSLInit();
AuthSSL::getAuthSSL() -> InitAuth(NULL, NULL, NULL, "");
rsAccounts = new RsAccountsDetail() ;
rsAccounts = new RsAccountsDetail();
// first check config directories, and set bootstrap values.
if(!rsAccounts->setupBaseDirectory(opt_base_dir))

View File

@ -198,60 +198,9 @@ bool RsLoginHandler::tryAutoLogin(const RsPeerId& ssl_id,std::string& ssl_passwd
return (status == 0);
/******************** OSX KeyChain stuff *****************************/
#else /* UNIX, but not HAS_GNOME_KEYRING or APPLE */
FILE* helpFile = RsDirUtil::rs_fopen(getAutologinFileName(ssl_id).c_str(), "r");
if(helpFile == NULL){
std::cerr << "\nFailed to open help file\n" << std::endl;
return false;
}
/* decrypt help */
int c ;
std::string passwd ;
while( (c = getc(helpFile)) != EOF )
passwd += (char)c ;
const int DAT_LEN = passwd.length();
const int KEY_DAT_LEN = RsInitConfig::load_cert.length();
unsigned char* key_data = (unsigned char*)RsInitConfig::load_cert.c_str();
unsigned char* indata = new unsigned char[DAT_LEN];
unsigned char* outdata = new unsigned char[DAT_LEN];
for(int i=0;i<DAT_LEN;++i)
indata[i] = passwd[i] ;
// if(fscanf(helpFile, "%s", indata) != 1)
// {
// std::cerr << "Can't read RSA key in help file " << helpFileName << ". Sorry." << std::endl ;
// return false ;
// }
RC4_KEY* key = new RC4_KEY;
RC4_set_key(key, KEY_DAT_LEN, key_data);
RC4(key, DAT_LEN, indata, outdata);
ssl_passwd.clear();
ssl_passwd.insert(0, (char*)outdata, DAT_LEN);
fclose(helpFile);
delete[] indata;
delete[] outdata;
if(key != NULL)
delete key;
return true;
#endif // APPLE
#endif // HAS_GNOME_KEYRING
/******* WINDOWS BELOW *****/
#else
#endif // HAS_GNOME_KEYRING
#else /******* WINDOWS BELOW *****/
/* try to load from file */
std::string entropy = getSSLPasswdFileName(ssl_id);
@ -419,6 +368,7 @@ bool RsLoginHandler::enableAutoLogin(const RsPeerId& ssl_id,const std::string& s
/***************** OSX KEYCHAIN ****************/
#else
#ifdef TODO_CODE_ROTTEN
/* WARNING: Autologin is inherently unsafe */
FILE* helpFile = RsDirUtil::rs_fopen(getAutologinFileName.c_str(), "w");
@ -450,6 +400,7 @@ bool RsLoginHandler::enableAutoLogin(const RsPeerId& ssl_id,const std::string& s
return true;
#endif // TODO_CODE_ROTTEN
#endif // __APPLE__
#endif // HAS_GNOME_KEYRING.
#else /* windows */

View File

@ -32,10 +32,19 @@
#include "rsserver/rsaccounts.h"
#include "rsdiscspace.h"
#include <util/rsthreads.h>
#ifndef WIN32
#include <sys/statvfs.h>
#ifdef __ANDROID__
# include <android/api-level.h>
#endif
#ifdef WIN32
# include <wtypes.h>
#elif defined(__ANDROID__) && (__ANDROID_API__ < 21)
# include <sys/vfs.h>
# define statvfs64 statfs
# warning statvfs64 is not supported with android platform < 21 falling back to statfs that is untested (may misbehave)
#else
#include <wtypes.h>
# include <sys/statvfs.h>
#endif
#define DELAY_BETWEEN_CHECKS 2

View File

@ -119,3 +119,21 @@ SOURCES += openpgpsdk/accumulate.c \
win32{
SOURCES += openpgpsdk/opsstring.c
}
################################# Android #####################################
android-g++ {
## Add this here and not in retroshare.pri because static library are very
## sensible to order in command line
LIBS += -L$$NDK_TOOLCHAIN_PATH/sysroot/usr/lib/ -lssl
INCLUDEPATH += $$NDK_TOOLCHAIN_PATH/sysroot/usr/include
DEPENDPATH += $$NDK_TOOLCHAIN_PATH/sysroot/usr/include
PRE_TARGETDEPS += $$NDK_TOOLCHAIN_PATH/sysroot/usr/lib/libssl.a
LIBS += -L$$NDK_TOOLCHAIN_PATH/sysroot/usr/lib/ -lcrypto
INCLUDEPATH += $$NDK_TOOLCHAIN_PATH/sysroot/usr/include
DEPENDPATH += $$NDK_TOOLCHAIN_PATH/sysroot/usr/include
PRE_TARGETDEPS += $$NDK_TOOLCHAIN_PATH/sysroot/usr/lib/libcrypto.a
}

View File

@ -460,7 +460,12 @@ callback_cmd_get_secret_key(const ops_parser_content_t *content_,ops_parse_cb_in
char *ops_get_passphrase(void)
{
#ifndef __ANDROID__
return ops_malloc_passphrase(getpass("Passphrase: "));
#else // __ANDROID__
return ops_malloc_passphrase("getpass not supported on android");
#warning "getpass not supported on android"
#endif // __ANDROID__
}
char *ops_malloc_passphrase(char *pp)

View File

@ -0,0 +1,24 @@
!include("../../retroshare.pri"): error("Could not include file ../../retroshare.pri")
TARGET = retroshare-android-service
QT += core network
QT -= gui
CONFIG += c++11
CONFIG += dll
android-g++:TEMPLATE = lib
!android-g++:TEMPLATE = app
SOURCES += service.cpp
DEPENDPATH *= ../../libresapi/src
INCLUDEPATH *= ../../libresapi/src
PRE_TARGETDEPS *= ../../libresapi/src/lib/libresapi.a
LIBS *= ../../libresapi/src/lib/libresapi.a
DEPENDPATH *= ../../libretroshare/src
INCLUDEPATH *= ../../libretroshare/src
PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a
LIBS *= ../../libretroshare/src/lib/libretroshare.a

View File

@ -0,0 +1,57 @@
/*
* RetroShare Android Service
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
*/
#include <QCoreApplication>
#include <QDebug>
#ifdef __ANDROID__
# include <QtAndroidExtras>
#endif
#include "retroshare/rsinit.h"
#include "api/ApiServer.h"
#include "api/ApiServerLocal.h"
#include "api/RsControlModule.h"
using namespace resource_api;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
ApiServer api;
RsControlModule ctrl_mod(argc, argv, api.getStateTokenServer(), &api, true);
api.addResourceHandler("control", dynamic_cast<resource_api::ResourceRouter*>(&ctrl_mod), &resource_api::RsControlModule::handleRequest);
QString sockPath = QString::fromStdString(RsAccounts::ConfigDirectory());
sockPath.append("/libresapi.sock");
qDebug() << "Listening on:" << sockPath;
ApiServerLocal apiServerLocal(&api, sockPath); (void) apiServerLocal;
#ifdef __ANDROID__
qDebug() << "Is service.cpp running as a service?" << QtAndroid::androidService().isValid();
qDebug() << "Is service.cpp running as an activity?" << QtAndroid::androidActivity().isValid();
#endif
while (!ctrl_mod.processShouldExit())
{
a.processEvents();
usleep(20000);
}
return 0;
}

View File

@ -26,11 +26,11 @@
#include "ui_ServerPage.h"
#include "RsAutoUpdatePage.h"
#include <inttypes.h>
#include <sys/socket.h>
class QNetworkReply;
class QNetworkAccessManager;
class BanListPeer;
struct sockaddr_storage;
class ServerPage: public ConfigPage
{

View File

@ -100,7 +100,7 @@ QString WebuiPage::helpText() const
// TODO: LIBRESAPI_LOCAL_SERVER Move in appropriate place
#ifdef LIBRESAPI_LOCAL_SERVER
apiServerLocal = new resource_api::ApiServerLocal(apiServer);
apiServerLocal = new resource_api::ApiServerLocal(apiServer, resource_api::ApiServerLocal::serverPath());
#endif
return ok;
}

View File

@ -24,6 +24,7 @@
#include <QString>
#include <inttypes.h>
#include <sys/socket.h>
class RsNetUtil
{

View File

@ -0,0 +1,5 @@
.build
.gradle
.idea
captures
local.properties

View File

@ -0,0 +1,136 @@
<?xml version="1.0"?>
<manifest package="org.retroshare.android.qml_app" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
<application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="RetroShare">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation" android:name=".RetroShareQmlActivity" android:label="RetroShare QML" android:screenOrientation="unspecified" android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<!-- Application to launch -->
<meta-data android:name="android.app.lib_name" android:value="retroshare-qml-app"/>
<!-- Application to launch -->
<!-- Application arguments -->
<!-- meta-data android:name="android.app.arguments" android:value="arg1 arg2 arg3"/ -->
<!-- Application arguments -->
<meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
<meta-data android:name="android.app.repository" android:value="default"/>
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
<meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
<!-- Deploy Qt libs as part of package -->
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
<meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
<!-- Run with local libs -->
<meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
<meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
<meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
<!-- Messages maps -->
<meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
<meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
<meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
<!-- Messages maps -->
<!-- Splash screen -->
<!-- meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/logo"/ -->
<!-- meta-data android:name="android.app.splash_screen_sticky" android:value="true"/ -->
<!-- Splash screen -->
<!-- Background running -->
<!-- Warning: changing this value to true may cause unexpected crashes if the
application still try to draw after
"applicationStateChanged(Qt::ApplicationSuspended)"
signal is sent! -->
<meta-data android:name="android.app.background_running" android:value="false"/>
<!-- Background running -->
<!-- auto screen scale factor -->
<meta-data android:name="android.app.auto_screen_scale_factor" android:value="false"/>
<!-- auto screen scale factor -->
<!-- extract android style -->
<!-- available android:values :
* full - useful QWidget & Quick Controls 1 apps
* minimal - useful for Quick Controls 2 apps, it is much faster than "full"
* none - useful for apps that don't use any of the above Qt modules
-->
<meta-data android:name="android.app.extract_android_style" android:value="full"/>
<!-- extract android style -->
</activity>
<receiver android:name=".BootCompletedReceiver" android:enabled="true" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<receiver android:name=".AppUpdatedReceiver" android:enabled="true" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
</intent-filter>
</receiver>
<!-- For adding service(s) please check: https://wiki.qt.io/AndroidServices -->
<service android:process=":rs" android:name=".RetroShareAndroidService" android:label="RetroShare Service" android:exported="true"> <!-- Added to be able to run the service from adb shell -->
<!-- android:process=":qt" is needed to force the service to run on a separate process than the Activity -->
<!-- Application arguments -->
<!-- meta-data android:name="android.app.arguments" android:value="-service"/ -->
<!-- Application arguments -->
<!-- If you are using the same application (.so file) for activity and also for service, then you
need to use *android.app.arguments* to pass some arguments to your service in order to know which
one is which.
-->
<!-- Application to launch -->
<meta-data android:name="android.app.lib_name" android:value="retroshare-android-service"/>
<!-- Application to launch -->
<!-- Ministro -->
<meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
<meta-data android:name="android.app.repository" android:value="default"/>
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
<meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
<!-- Deploy Qt libs as part of package -->
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
<meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
<!-- Run with local libs -->
<meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
<meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
<meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
<!-- Messages maps -->
<meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
<meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
<meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
<!-- Messages maps -->
<!-- Background running -->
<meta-data android:name="android.app.background_running" android:value="true"/>
<!-- Background running -->
</service>
</application>
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="18"/>
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
Remove the comment if you do not require these default permissions. -->
<!-- %%INSERT_PERMISSIONS -->
<!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
Remove the comment if you do not require these default features. -->
<!-- %%INSERT_FEATURES -->
<!-- Added by G10h4ck: Needed permission for autostart at boot -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
</manifest>

View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="android" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<afterSyncTasks>
<task>generateDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/../../../../qt5/qtbase/src/android/java/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/../../../../qt5/qtbase/src/android/java/res;file://$MODULE_DIR$/res" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/.build/intermediates/classes/debug" />
<output-test url="file://$MODULE_DIR$/.build/intermediates/classes/test/debug" />
<exclude-output />
<content url="file://$MODULE_DIR$/../../../../qt5/qtbase/src/android/java/res">
<sourceFolder url="file://$MODULE_DIR$/../../../../qt5/qtbase/src/android/java/res" type="java-resource" />
</content>
<content url="file://$MODULE_DIR$/../../../../qt5/qtbase/src/android/java/src">
<sourceFolder url="file://$MODULE_DIR$/../../../../qt5/qtbase/src/android/java/src" isTestSource="false" />
</content>
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/.build/generated/source/r/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/.build/generated/source/aidl/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/.build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/.build/generated/source/rs/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/.build/generated/res/rs/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/.build/generated/res/generated/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/.build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/.build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/.build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/.build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/.build/generated/res/rs/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/.build/generated/res/generated/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/.build/intermediates/assets" />
<excludeFolder url="file://$MODULE_DIR$/.build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/.build/intermediates/manifests" />
<excludeFolder url="file://$MODULE_DIR$/.build/intermediates/mockable-android-18.jar" />
<excludeFolder url="file://$MODULE_DIR$/.build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/.build/intermediates/resources" />
<excludeFolder url="file://$MODULE_DIR$/.build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/.build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/.build/outputs" />
</content>
<orderEntry type="jdk" jdkName="Android API 18 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" scope="TEST" name="mockable-android-18" level="project" />
</component>
</module>

View File

@ -0,0 +1,57 @@
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.1.0'
}
}
allprojects {
repositories {
jcenter()
}
}
apply plugin: 'com.android.application'
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
android {
/*******************************************************
* The following variables:
* - androidBuildToolsVersion,
* - androidCompileSdkVersion
* - qt5AndroidDir - holds the path to qt android files
* needed to build any Qt application
* on Android.
*
* are defined in gradle.properties file. This file is
* updated by QtCreator and androiddeployqt tools.
* Changing them manually might break the compilation!
*******************************************************/
compileSdkVersion androidCompileSdkVersion.toInteger()
buildToolsVersion androidBuildToolsVersion
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java']
aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl']
res.srcDirs = [qt5AndroidDir + '/res', 'res']
resources.srcDirs = ['src']
renderscript.srcDirs = ['src']
assets.srcDirs = ['assets']
jniLibs.srcDirs = ['libs']
}
}
lintOptions {
abortOnError false
}
}

View File

@ -0,0 +1,36 @@
Activity Resolver Table:
Non-Data Actions:
android.intent.action.MAIN:
42420338 org.retroshare.android.qml_app/.RetroShareQmlActivity filter 42424830
Receiver Resolver Table:
Non-Data Actions:
android.intent.action.BOOT_COMPLETED:
4245c230 org.retroshare.android.qml_app/.BootCompletedReceiver filter 4245c360
Packages:
Package [org.retroshare.android.qml_app] (4289b2f8):
userId=10168 gids=[3003, 1015, 1028]
pkg=Package{42244e18 org.retroshare.android.qml_app}
codePath=/data/app/org.retroshare.android.qml_app-2.apk
resourcePath=/data/app/org.retroshare.android.qml_app-2.apk
nativeLibraryPath=/data/app-lib/org.retroshare.android.qml_app-2
versionCode=1 targetSdk=18
versionName=1.0
applicationInfo=ApplicationInfo{4232af50 org.retroshare.android.qml_app}
flags=[ DEBUGGABLE HAS_CODE ALLOW_CLEAR_USER_DATA ALLOW_BACKUP ]
dataDir=/data/data/org.retroshare.android.qml_app
supportsScreens=[small, medium, large, xlarge, resizeable, anyDensity]
timeStamp=2016-08-22 16:53:12
firstInstallTime=2016-08-22 16:47:19
lastUpdateTime=2016-08-22 16:53:30
signatures=PackageSignatures{4233b1e0 [4265b018]}
permissionsFixed=true haveGids=true installStatus=1
pkgFlags=[ DEBUGGABLE HAS_CODE ALLOW_CLEAR_USER_DATA ALLOW_BACKUP ]
User 0: installed=true stopped=false notLaunched=false enabled=0
grantedPermissions:
android.permission.READ_EXTERNAL_STORAGE
android.permission.RECEIVE_BOOT_COMPLETED
android.permission.ACCESS_NETWORK_STATE
android.permission.WRITE_EXTERNAL_STORAGE
android.permission.INTERNET

View File

@ -0,0 +1,9 @@
## This file is automatically generated by QtCreator.
#
# This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
androidBuildToolsVersion=24.0.1
androidCompileSdkVersion=18
buildDir=.build
qt5AndroidDir=/opt/Qt5.7.0/5.7/android_armv7/src/android/java

Binary file not shown.

View File

@ -0,0 +1,6 @@
#Wed Apr 10 15:27:10 PDT 2013
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip

164
retroshare-qml-app/src/android/gradlew vendored Executable file
View File

@ -0,0 +1,164 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

View File

@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -0,0 +1,25 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>
<array name="qt_sources">
<item>https://download.qt.io/ministro/android/qt5/qt-5.7</item>
</array>
<!-- The following is handled automatically by the deployment tool. It should
not be edited manually. -->
<array name="bundled_libs">
<!-- %%INSERT_EXTRA_LIBS%% -->
</array>
<array name="qt_libs">
<!-- %%INSERT_QT_LIBS%% -->
</array>
<array name="bundled_in_lib">
<!-- %%INSERT_BUNDLED_IN_LIB%% -->
</array>
<array name="bundled_in_assets">
<!-- %%INSERT_BUNDLED_IN_ASSETS%% -->
</array>
</resources>

View File

@ -0,0 +1,36 @@
/*
* RetroShare Android Service
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
*/
package org.retroshare.android.qml_app;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class AppUpdatedReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
Log.i("AppUpdatedReceiver", "onReceive() Restarting RetroShare Android Service After Update");
Intent myIntent = new Intent(context, RetroShareAndroidService.class);
context.stopService(myIntent);
context.startService(myIntent);
}
}

View File

@ -0,0 +1,33 @@
/*
* RetroShare Android Service
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
*/
package org.retroshare.android.qml_app;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class BootCompletedReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
Intent myIntent = new Intent(context, RetroShareAndroidService.class);
context.startService(myIntent);
}
}

View File

@ -0,0 +1,23 @@
/*
* RetroShare Android Service
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
*/
package org.retroshare.android.qml_app;
import org.qtproject.qt5.android.bindings.QtService;
public class RetroShareAndroidService extends QtService {}

View File

@ -0,0 +1,53 @@
/*
* RetroShare Android QML App
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
*/
package org.retroshare.android.qml_app;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import org.qtproject.qt5.android.bindings.QtActivity;
public class RetroShareQmlActivity extends QtActivity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
if (!isMyServiceRunning(RetroShareAndroidService.class))
{
Log.i("RetroShareQmlActivity", "onCreate(): RetroShareAndroidService is not running, let's start it by Intent");
Intent rsIntent = new Intent(this, RetroShareAndroidService.class);
startService(rsIntent);
}
else Log.v("RetroShareQmlActivity", "onCreate(): RetroShareAndroidService already running");
super.onCreate(savedInstanceState);
}
private boolean isMyServiceRunning(Class<?> serviceClass)
{
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE))
if (serviceClass.getName().equals(service.service.getClassName()))
return true;
return false;
}
}

View File

@ -0,0 +1,15 @@
#ifndef DEBUGUTILS_H
#define DEBUGUTILS_H
#include <QDebug>
//To switch between debugging and normal mode, un-/comment next line
#define DEBUGGING
#ifdef DEBUGGING
#define myDebug(line) qDebug() << "| FILE:" << __FILE__ << " | LINE_NUMBER:"\
<< __LINE__ << " | FUNCTION:" << __FUNCTION__ << " | CONTENT:" << line
#else
#define myDebug(line)
#endif
#endif // DEBUGUTILS_H

View File

@ -0,0 +1,13 @@
unix:!android {
isEmpty(target.path) {
qnx {
target.path = /tmp/$${TARGET}/bin
} else {
target.path = /opt/$${TARGET}/bin
}
export(target.path)
}
INSTALLS += target
}
export(INSTALLS)

View File

@ -0,0 +1,84 @@
/*
* RetroShare Android QML App
* Copyright (C) 2016 Gioacchino Mazzurco <gio@eigenlab.org>
* Copyright (C) 2016 Manu Pineda <manu@cooperativa.cat>
*
* 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/>.
*/
#include "libresapilocalclient.h"
#include "debugutils.h"
#include <QChar>
void LibresapiLocalClient::openConnection(QString socketPath)
{
connect(& mLocalSocket, SIGNAL(error(QLocalSocket::LocalSocketError)),
this, SLOT(socketError(QLocalSocket::LocalSocketError)));
connect(& mLocalSocket, SIGNAL(readyRead()),
this, SLOT(read()));
mLocalSocket.connectToServer(socketPath);
}
int LibresapiLocalClient::request(const QString & path, const QString & jsonData)
{
qDebug() << "LibresapiLocalClient::request()" << path << jsonData;
QByteArray data;
data.append(path); data.append('\n');
data.append(jsonData); data.append('\n');
mLocalSocket.write(data);
return 1;
}
void LibresapiLocalClient::socketError(QLocalSocket::LocalSocketError)
{
myDebug("error!!!!\n" + mLocalSocket.errorString());
}
void LibresapiLocalClient::read()
{
receivedBytes = mLocalSocket.readLine();
qDebug() << receivedBytes;
if(parseResponse()) // pensar en fer un buffer per parsejar, per evitar errors.
emit goodResponseReceived(QString(receivedBytes));
else
{
QString errMess = "The message was not understood!\n"
"It should be a JSON formatted text file\n"
"Its contents were:\n" + receivedBytes;
myDebug(errMess.replace(QChar('\n'), QChar::LineSeparator));
}
}
bool LibresapiLocalClient::parseResponse()
{
QJsonParseError error;
json = QJsonDocument::fromJson(receivedBytes, &error);
myDebug(QString(json.toJson()).replace(QChar('\n'), QChar::LineSeparator));
if(error.error == QJsonParseError::NoError){
return true;
}
myDebug(error.errorString());
return false;
}
const QJsonDocument & LibresapiLocalClient::getJson()
{
return json;
}

View File

@ -0,0 +1,56 @@
/*
* libresapi local socket client
* Copyright (C) 2016 Gioacchino Mazzurco <gio@eigenlab.org>
* Copyright (C) 2016 Manu Pineda <manu@cooperativa.cat>
*
* 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/>.
*/
#ifndef LIBRESAPILOCALCLIENT_H
#define LIBRESAPILOCALCLIENT_H
#include <QLocalSocket>
#include <QDir>
#include <QJsonDocument>
#include <QVector>
class LibresapiLocalClient : public QObject
{
Q_OBJECT
public:
LibresapiLocalClient() : mLocalSocket(this) {}
// potser abstreure el següent amb QUrl urlPath (path) i amb QJson jsonData.
Q_INVOKABLE int request(const QString & path, const QString & jsonData);
const QJsonDocument & getJson();
Q_INVOKABLE void openConnection(QString socketPath);
private:
QLocalSocket mLocalSocket;
QByteArray receivedBytes;
QJsonDocument json;
//QVector<QJsonDocument> responses;
bool parseResponse(); //std::string msg);
private slots:
void socketError(QLocalSocket::LocalSocketError error);
void read();
signals:
void goodResponseReceived(const QString & msg);//, int requestId);
};
#endif // LIBRESAPILOCALCLIENT_H

View File

@ -0,0 +1,61 @@
/*
* RetroShare Android QML App
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
*/
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQmlComponent>
#include <QDebug>
#ifdef __ANDROID__
# include <QtAndroidExtras>
#endif
#include <QFileInfo>
#include <QDateTime>
#include "libresapilocalclient.h"
#include "retroshare/rsinit.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
qmlRegisterType<LibresapiLocalClient>(
"org.retroshare.qml_components.LibresapiLocalClient", 1, 0,
"LibresapiLocalClient");
QString sockPath = QString::fromStdString(RsAccounts::ConfigDirectory());
sockPath.append("/libresapi.sock");
engine.rootContext()->setContextProperty("apiSocketPath", sockPath);
engine.load(QUrl(QLatin1String("qrc:/qml/main.qml")));
QFileInfo fileInfo(sockPath);
#ifdef __ANDROID__
qDebug() << "Is main.cpp running as a service?" << QtAndroid::androidService().isValid();
qDebug() << "Is main.cpp running as an activity?" << QtAndroid::androidActivity().isValid();
#endif
qDebug() << "QML APP:" << sockPath << fileInfo.exists() << fileInfo.lastModified().toString();
return app.exec();
}

View File

@ -0,0 +1,26 @@
<RCC>
<qresource prefix="/">
<file>qml/main.qml</file>
<file>qml/icons/star-2-128.png</file>
<file>qml/icons/settings-4-128.png</file>
<file>qml/icons/email-128.png</file>
<file>qml/icons/contacts-128.png</file>
<file>qml/PostedMsgDelegate.qml</file>
<file>qml/GxsService.qml</file>
<file>qml/GxsIdDelegate.qml</file>
<file>qml/GxsGroupDelegate.qml</file>
<file>qml/ForumMsgDelegate.qml</file>
<file>qml/ContactBox.qml</file>
<file>qml/ChannelMsgDelegate.qml</file>
<file>qml/ChannelGroupDelegate.qml</file>
<file>qml/ApplicationBar.qml</file>
<file>qml/AppButton.qml</file>
<file>qml/Locations.qml</file>
<file>qml/jsonpath.js</file>
<file>qml/JSONListModel.qml</file>
<file>qml/Contacts.qml</file>
<file>qml/AddTrustedNode.qml</file>
<file>qml/RsLoginPassView.qml</file>
<file>qml/TrustedNodesView.qml</file>
</qresource>
</RCC>

View File

@ -0,0 +1,78 @@
import QtQuick 2.0
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.3
import org.retroshare.qml_components.LibresapiLocalClient 1.0
Item
{
function refreshData() { rsApi.request("/peers/self/certificate/", "") }
Component.onCompleted:
{
rsApi.openConnection(apiSocketPath)
refreshData()
}
onFocusChanged: focus && refreshData()
LibresapiLocalClient
{
id: rsApi
onGoodResponseReceived:
{
var jsonData = JSON.parse(msg)
if(jsonData && jsonData.data && jsonData.data.cert_string)
myKeyField.text = jsonData.data.cert_string
}
}
ColumnLayout
{
anchors.fill: parent
Button
{
id: bottomButton
text: "Add trusted node"
onClicked:
{
console.log("retroshare addtrusted: ", otherKeyField.text)
var jsonData =
{
cert_string: otherKeyField.text,
flags:
{
allow_direct_download: true,
allow_push: false,
require_whitelist: false,
}
}
console.log("retroshare addtrusted jsonData: ", JSON.stringify(jsonData))
//rsApi.request("/peers/examine_cert/", JSON.stringify({ cert_string: otherKeyField.text }))
rsApi.request("PUT /peers", JSON.stringify(jsonData))
}
}
Button
{
text: "Copy"
onClicked:
{
myKeyField.selectAll()
myKeyField.copy()
}
}
Button
{
text: "Paste"
onClicked:
{
otherKeyField.selectAll()
otherKeyField.paste()
}
}
TextField { id: myKeyField }
TextField { id: otherKeyField }
}
}

View File

@ -0,0 +1,30 @@
import QtQuick 2.2
import QtQuick.Layouts 1.1
import "."
Rectangle {
id: appButton
property alias icon: appIcon.source
signal buttonClicked
width: parent.height
height: parent.height
color: "#00000000"
Image {
id: appIcon
anchors.centerIn: parent
width: 25
height: 25
}
MouseArea {
hoverEnabled: false
anchors.fill: parent
onClicked: {
appButton.buttonClicked()
}
}
}

View File

@ -0,0 +1,37 @@
import QtQuick 2.2
import QtQuick.Layouts 1.1
import "."
Rectangle {
id: status
anchors.fill: parent
color: "#336699" //"#FF7733"
height: 50
default property alias contents: placeholder.children
RowLayout {
id: placeholder
spacing: 0
width: 200
height: parent.height
anchors.top: parent.top
anchors.left: parent.left
}
ContactBox {
width: 200
height: parent.height
anchors.top: parent.top
anchors.right: parent.right
icon: "icons/contacts-128.png"
name: "Vade Retro"
status: "Away"
}
}

View File

@ -0,0 +1,33 @@
import QtQuick 2.2
import "."
Item {
id: item
width: parent.width
height: 50
Column {
Text { text: '<b>' + model.GroupName + '</b>' }
Text { text: GroupId }
}
MouseArea {
hoverEnabled: false
anchors.fill: parent
onClicked: {
item.ListView.view.currentIndex = index
channelMsgModel.updateEntries(model.GroupId)
console.log("Clicked on Channel GroupId: " + model.GroupId)
}
}
Rectangle {
width: parent.width
height: 1
color: "#AAAAAA"
anchors.left: parent.left
anchors.top: parent.bottom
}
}

View File

@ -0,0 +1,42 @@
import QtQuick 2.2
import "."
Item {
id: msgDelegate
width: parent.width
height: 150
Column {
Text { text: '<b>MsgId:</b> ' + AuthorId }
Text { text: '<b>AuthorId:</b> ' + AuthorId }
Row {
Text { text: '<b>Name:</b> ' + MsgName }
Text { text: ' <b>PublishTs:</b> ' + PublishTs }
}
Text { text: '<b>Msg:</b> ' + Msg }
Row {
Text { text: '<b>NumberFiles:</b> ' + NumberFiles }
Text { text: ' <b>TotalFileSize:</b> ' + TotalFileSize }
}
Text { text: '<b>FileNames:</b> ' + FileNames }
Text { text: '<b>FileSizes:</b> ' + FileSizes }
Text { text: '<b>FileHashes:</b> ' + FileHashes }
Row {
Text { text: '<b>HaveVoted:</b> ' + HaveVoted }
Text { text: ' <b>UpVotes:</b> ' + UpVotes }
Text { text: ' <b>DownVotes:</b> ' + DownVotes }
Text { text: ' <b>Comments:</b> ' + Comments }
}
}
MouseArea {
hoverEnabled: false
anchors.fill: parent
onClicked: {
item.ListView.view.currentIndex = index
}
}
}

View File

@ -0,0 +1,61 @@
import QtQuick 2.2
import "."
Item {
property alias icon: contactIcon.source
property alias name: contactName.text
property alias status: contactStatus.text
Rectangle {
anchors.fill: parent
color: "#00000000"
Image {
id: contactIcon
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
width: 40
height: 40
source: "icons/contacts-128.png"
}
Rectangle {
height: contactIcon.height
anchors.verticalCenter: parent.verticalCenter
anchors.left: contactIcon.right
color: parent.color
Text {
id: contactName
text: "Username"
anchors.left: parent.left
anchors.leftMargin: 10
anchors.bottom: contactStatus.top
anchors.bottomMargin: 2
horizontalAlignment: Text.AlignHCenter
font.pointSize: 14
font.bold: false
color: "#FFFFFF"
}
Text {
id: contactStatus
text: "Hello world!"
anchors.left: parent.right
anchors.leftMargin: 10
anchors.bottom: parent.bottom
anchors.bottomMargin: 1
horizontalAlignment: Text.AlignHCenter
font.pointSize: 10
font.bold: false
color: "#FFFFFF"
}
}
}
}

View File

@ -0,0 +1,52 @@
/*
* RetroShare Android QML App
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.0
import QtQuick.Controls 1.4
import org.retroshare.qml_components.LibresapiLocalClient 1.0
Item
{
function refreshData() { rsApi.request("/identity/*/", "") }
onFocusChanged: focus && refreshData()
LibresapiLocalClient
{
id: rsApi
onGoodResponseReceived: locationsModel.json = msg
Component.onCompleted: { openConnection(apiSocketPath) }
}
JSONListModel
{
id: locationsModel
query: "$.data[*]"
}
ListView
{
id: locationsListView
width: parent.width
height: 300
model: locationsModel.model
delegate: Text { text: model.name }
}
Text { text: "Contacts View"; anchors.bottom: parent.bottom }
}

View File

@ -0,0 +1,41 @@
import QtQuick 2.2
import "."
Item {
id: msgDelegate
width: parent.width
height: col.height
Column {
id: col
Text { text: '<b>MsgId:</b> ' + AuthorId }
Text { text: '<b>AuthorId:</b> ' + AuthorId }
Row {
Text { text: '<b>Name:</b> ' + MsgName }
Text { text: ' <b>PublishTs:</b> ' + PublishTs }
}
Text {
wrapMode: Text.Wrap
text: '<b>Msg:</b> ' + Msg
}
}
MouseArea {
hoverEnabled: false
anchors.fill: parent
onClicked: {
item.ListView.view.currentIndex = index
}
}
Rectangle {
width: parent.width
height: 2
color: "#AAAAAA"
anchors.left: parent.left
anchors.top: parent.bottom
}
}

View File

@ -0,0 +1,26 @@
import QtQuick 2.2
import "."
Item {
id: item
property var msgModel: {}
width: parent.width
height: 50
Column {
Text { text: '<b>Name:</b> ' + model.GroupName }
Text { text: '<b>Number:</b> ' + GroupId }
}
MouseArea {
hoverEnabled: false
anchors.fill: parent
onClicked: {
item.ListView.view.currentIndex = index
item.msgModel.updateEntries(model.GroupId)
}
}
}

View File

@ -0,0 +1,33 @@
import QtQuick 2.2
import "."
Item {
id: item
width: parent.width
height: 50
Column {
Text { text: '<b>' + model.GroupName + '</b>' }
Text { text: GroupId }
}
MouseArea {
hoverEnabled: false
anchors.fill: parent
onClicked: {
item.ListView.view.currentIndex = index
//channelMsgModel.updateEntries(model.GroupId)
//console.log("Clicked on Channel GroupId: " + model.GroupId)
}
}
Rectangle {
width: parent.width
height: 1
color: "#AAAAAA"
anchors.left: parent.left
anchors.top: parent.bottom
}
}

View File

@ -0,0 +1,119 @@
import QtQuick 2.2
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.1
import "."
Item {
id: gxsService
property alias icon: sideIcon.source
property alias title: sideTitle.text
property alias groupDelegate: sideList.delegate
property alias groupModel: sideList.model
property alias msgDelegate: mainList.delegate
property alias msgModel: mainList.model
RowLayout {
spacing: 0
anchors.fill: parent
Rectangle {
id: sideBar
width: 200
Layout.fillHeight: true
Rectangle {
id: sideHeader
width: parent.width
height: 30
Text {
id: sideTitle
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 10
width: 20
height: 20
text: "Service"
color: "#333333"
}
Image {
id: sideIcon
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 10
width: 20
height: 20
source: "icons/contacts-128.png"
}
}
Rectangle {
id: sideListBox
width: parent.width
anchors.top: sideHeader.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
ListView {
id: sideList
anchors.fill: parent
delegate: GxsGroupDelegate {
msgModel: mainList.model
}
// section.
section.property: "SubscribeStatus"
section.criteria: ViewSection.FullString
section.delegate: Rectangle {
width: sideListBox.width
height: childrenRect.height
color: "blue"
Text {
text: section
font.bold: true
font.pixelSize: 20
}
}
clip: true
highlight: Rectangle { color: "lightsteelblue"; radius: 5 }
focus: true
onCurrentItemChanged: {
console.log("SideBar Item Changed on " + gxsService.title)
}
}
}
}
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
ListView {
id: mainList
anchors.fill: parent
clip: true
highlight: Rectangle { color: "lightsteelblue"; radius: 5 }
focus: true
onCurrentItemChanged: {
console.log("item changed")
}
}
}
}
}

View File

@ -0,0 +1,51 @@
/* JSONListModel - a QML ListModel with JSON and JSONPath support
*
* Copyright (c) 2012 Romain Pokrzywka (KDAB) (romain@kdab.com)
* Licensed under the MIT licence (http://opensource.org/licenses/mit-license.php)
*/
import QtQuick 2.0
import "jsonpath.js" as JSONPath
Item {
property string source: ""
property string json: ""
property string query: ""
property ListModel model : ListModel { id: jsonModel }
property alias count: jsonModel.count
onSourceChanged: {
var xhr = new XMLHttpRequest;
xhr.open("GET", source);
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE)
json = xhr.responseText;
}
xhr.send();
}
onJsonChanged: updateJSONModel()
onQueryChanged: updateJSONModel()
function updateJSONModel() {
jsonModel.clear();
if ( json === "" )
return;
var objectArray = parseJSONString(json, query);
for ( var key in objectArray ) {
var jo = objectArray[key];
jsonModel.append( jo );
}
}
function parseJSONString(jsonString, jsonPathQuery) {
var objectArray = JSON.parse(jsonString);
if ( jsonPathQuery !== "" )
objectArray = JSONPath.jsonPath(objectArray, jsonPathQuery);
return objectArray;
}
}

View File

@ -0,0 +1,192 @@
/*
* RetroShare Android QML App
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.0
import QtQuick.Controls 1.4
import org.retroshare.qml_components.LibresapiLocalClient 1.0
Item
{
id: locationView
state: "selectLocation"
property var qParent
property bool attemptLogin: false
property string password
property string sslid
states:
[
State
{
name: "selectLocation"
PropertyChanges { target: locationsListView; visible: true }
PropertyChanges { target: bottomButton; visible: true }
PropertyChanges { target: loginView; visible: false }
},
State
{
name: "createLocation"
PropertyChanges { target: locationsListView; visible: false }
PropertyChanges { target: bottomButton; visible: false }
PropertyChanges
{
target: loginView
visible: true
buttonText: "Save"
onSubmit:
{
var jsonData = { pgp_name: login, ssl_name: login, pgp_password: password }
rsApi.request("/control/create_location/", JSON.stringify(jsonData))
locationView.state = "selectLocation"
}
}
},
State
{
name: "login"
PropertyChanges { target: locationsListView; visible: false }
PropertyChanges { target: bottomButton; visible: false }
PropertyChanges
{
target: loginView
visible: true
onSubmit:
{
locationView.password = password
console.log("locationView.sslid: ", locationView.sslid)
rsApi.request("/control/login/", JSON.stringify({id: locationView.sslid}))
locationView.attemptLogin = true
busyIndicator.running = true
attemptTimer.start()
}
}
}
]
function requestLocationsList() { rsApi.request("/control/locations/", "") }
onFocusChanged: focus && requestLocationsList()
LibresapiLocalClient
{
id: rsApi
Component.onCompleted:
{
openConnection(apiSocketPath)
locationView.requestLocationsList()
}
onGoodResponseReceived:
{
var jsonData = JSON.parse(msg)
if(jsonData)
{
if(jsonData.data)
{
if(jsonData.data[0] && jsonData.data[0].pgp_id)
{
// if location list update
locationsModel.json = msg
busyIndicator.running = false
}
if (jsonData.data.key_name)
{
if(jsonData.data.want_password)
{
// if Server requested password
var jsonPass = { password: locationView.password }
rsApi.request("/control/password/", JSON.stringify(jsonPass))
locationView.attemptLogin = false
console.debug("RS core asked for password")
}
else
{
// if Already logged in
bottomButton.enabled = false
bottomButton.text = "Already logged in"
locationView.attemptLogin = false
busyIndicator.running = false
locationView.state = "selectLocation"
locationsListView.enabled = false
console.debug("Already logged in")
}
}
}
}
}
}
BusyIndicator { id: busyIndicator; anchors.centerIn: parent }
JSONListModel
{
id: locationsModel
query: "$.data[*]"
}
ListView
{
id: locationsListView
width: parent.width
anchors.top: parent.top
anchors.bottom: bottomButton.top
model: locationsModel.model
delegate: Button
{
text: model.name
onClicked:
{
loginView.login = text
locationView.sslid = model.id
locationView.state = "login"
}
}
visible: false
}
Button
{
id: bottomButton
text: "Create new location"
anchors.bottom: parent.bottom
onClicked: locationView.state = "createLocation"
}
RsLoginPassView
{
id: loginView
visible: false
anchors.fill: parent
}
Timer
{
id: attemptTimer
interval: 500
repeat: true
onTriggered:
{
if(locationView.focus)
locationView.requestLocationsList()
if (locationView.attemptLogin)
rsApi.request("/control/password/", "")
}
}
}

View File

@ -0,0 +1,40 @@
import QtQuick 2.2
import "."
Item {
id: msgDelegate
width: parent.width
height: 150
Column {
Text { text: '<b>MsgId:</b> ' + AuthorId }
Text { text: '<b>AuthorId:</b> ' + AuthorId }
Row {
Text { text: '<b>Name:</b> ' + MsgName }
Text { text: ' <b>PublishTs:</b> ' + PublishTs }
}
Text { text: '<b>Link:</b> ' + Link }
Text { text: '<b>Notes:</b> ' + Notes }
Row {
Text { text: '<b>Hot:</b> ' + HotScore }
Text { text: ' <b>Top:</b> ' + HotScore }
Text { text: ' <b>New:</b> ' + HotScore }
}
Row {
Text { text: '<b>HaveVoted:</b> ' + HaveVoted }
Text { text: ' <b>UpVotes:</b> ' + UpVotes }
Text { text: ' <b>DownVotes:</b> ' + DownVotes }
Text { text: ' <b>Comments:</b> ' + Comments }
}
}
MouseArea {
hoverEnabled: false
anchors.fill: parent
onClicked: {
item.ListView.view.currentIndex = index
}
}
}

View File

@ -0,0 +1,52 @@
/*
* RetroShare Android QML App
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.0
import QtQuick.Layouts 1.3
import QtQuick.Controls 1.4
import QtQml 2.2
import org.retroshare.qml_components.LibresapiLocalClient 1.0
Item
{
id: loginView
property string buttonText: "Login"
property string login
property string password
signal submit(string login, string password)
ColumnLayout
{
id: inputView
width: parent.width
anchors.top: parent.top
anchors.bottom: bottomButton.top
Row { Text {text: "Name:" } TextField { id: nameField; text: loginView.login } }
Row { Text {text: "Password:" } TextField { id: passwordField; text: loginView.password } }
}
Button
{
id: bottomButton
text: loginView.buttonText
anchors.bottom: parent.bottom
anchors.right: parent.right
onClicked: loginView.submit(nameField.text, passwordField.text)
}
}

View File

@ -0,0 +1,63 @@
/*
* RetroShare Android QML App
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.0
import QtQuick.Controls 1.4
import org.retroshare.qml_components.LibresapiLocalClient 1.0
import "jsonpath.js" as JSONPath
Item
{
function refreshData() { rsApi.request("/peers/*", "") }
onFocusChanged: focus && refreshData()
LibresapiLocalClient
{
id: rsApi
onGoodResponseReceived: jsonModel.json = msg
Component.onCompleted: { openConnection(apiSocketPath) }
}
JSONListModel
{
id: jsonModel
query: "$.data[*]"
}
ListView
{
width: parent.width
anchors.top: parent.top
anchors.bottom: bottomButton.top
model: jsonModel.model
delegate: Text
{
text: model.name
onTextChanged: color = JSONPath.jsonPath(JSON.parse(jsonModel.json), "$.data[?(@.pgp_id=='"+model.pgp_id+"')].locations[*].is_online").reduce(function(cur,acc){return cur || acc}, false) ? "lime" : "darkslategray"
}
}
Button
{
id: bottomButton
text: "Add Trusted Node"
anchors.bottom: parent.bottom
onClicked: swipeView.currentIndex = 3
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,88 @@
/* JSONPath 0.8.5 - XPath for JSON
*
* Copyright (c) 2007 Stefan Goessner (goessner.net)
* Licensed under the MIT (MIT-LICENSE.txt) licence.
*
*/
function jsonPath(obj, expr, arg) {
var P = {
resultType: arg && arg.resultType || "VALUE",
result: [],
normalize: function(expr) {
var subx = [];
return expr.replace(/[\['](\??\(.*?\))[\]']|\['(.*?)'\]/g, function($0,$1,$2){return "[#"+(subx.push($1||$2)-1)+"]";}) /* http://code.google.com/p/jsonpath/issues/detail?id=4 */
.replace(/'?\.'?|\['?/g, ";")
.replace(/;;;|;;/g, ";..;")
.replace(/;$|'?\]|'$/g, "")
.replace(/#([0-9]+)/g, function($0,$1){return subx[$1];});
},
asPath: function(path) {
var x = path.split(";"), p = "$";
for (var i=1,n=x.length; i<n; i++)
p += /^[0-9*]+$/.test(x[i]) ? ("["+x[i]+"]") : ("['"+x[i]+"']");
return p;
},
store: function(p, v) {
if (p) P.result[P.result.length] = P.resultType == "PATH" ? P.asPath(p) : v;
return !!p;
},
trace: function(expr, val, path) {
if (expr !== "") {
var x = expr.split(";"), loc = x.shift();
x = x.join(";");
if (val && val.hasOwnProperty(loc))
P.trace(x, val[loc], path + ";" + loc);
else if (loc === "*")
P.walk(loc, x, val, path, function(m,l,x,v,p) { P.trace(m+";"+x,v,p); });
else if (loc === "..") {
P.trace(x, val, path);
P.walk(loc, x, val, path, function(m,l,x,v,p) { typeof v[m] === "object" && P.trace("..;"+x,v[m],p+";"+m); });
}
else if (/^\(.*?\)$/.test(loc)) // [(expr)]
P.trace(P.eval(loc, val, path.substr(path.lastIndexOf(";")+1))+";"+x, val, path);
else if (/^\?\(.*?\)$/.test(loc)) // [?(expr)]
P.walk(loc, x, val, path, function(m,l,x,v,p) { if (P.eval(l.replace(/^\?\((.*?)\)$/,"$1"), v instanceof Array ? v[m] : v, m)) P.trace(m+";"+x,v,p); }); // issue 5 resolved
else if (/^(-?[0-9]*):(-?[0-9]*):?([0-9]*)$/.test(loc)) // [start:end:step] phyton slice syntax
P.slice(loc, x, val, path);
else if (/,/.test(loc)) { // [name1,name2,...]
for (var s=loc.split(/'?,'?/),i=0,n=s.length; i<n; i++)
P.trace(s[i]+";"+x, val, path);
}
}
else
P.store(path, val);
},
walk: function(loc, expr, val, path, f) {
if (val instanceof Array) {
for (var i=0,n=val.length; i<n; i++)
if (i in val)
f(i,loc,expr,val,path);
}
else if (typeof val === "object") {
for (var m in val)
if (val.hasOwnProperty(m))
f(m,loc,expr,val,path);
}
},
slice: function(loc, expr, val, path) {
if (val instanceof Array) {
var len=val.length, start=0, end=len, step=1;
loc.replace(/^(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)$/g, function($0,$1,$2,$3){start=parseInt($1||start);end=parseInt($2||end);step=parseInt($3||step);});
start = (start < 0) ? Math.max(0,start+len) : Math.min(len,start);
end = (end < 0) ? Math.max(0,end+len) : Math.min(len,end);
for (var i=start; i<end; i+=step)
P.trace(i+";"+expr, val, path);
}
},
eval: function(x, _v, _vname) {
try { return $ && _v && eval(x.replace(/(^|[^\\])@/g, "$1_v").replace(/\\@/g, "@")); } // issue 7 : resolved ..
catch(e) { throw new SyntaxError("jsonPath: " + e.message + ": " + x.replace(/(^|[^\\])@/g, "$1_v").replace(/\\@/g, "@")); } // issue 7 : resolved ..
}
};
var $ = obj;
if (expr && obj && (P.resultType == "VALUE" || P.resultType == "PATH")) {
P.trace(P.normalize(expr).replace(/^\$;?/,""), obj, "$"); // issue 6 resolved
return P.result.length ? P.result : false;
}
}

View File

@ -0,0 +1,246 @@
/*
* RetroShare Android QML App
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.2
import QtQuick.Controls 1.4
import org.retroshare.qml_components.LibresapiLocalClient 1.0
ApplicationWindow
{
id: mainWindow
visible: true
title: qsTr("RSChat")
width: 400
height: 400
Rectangle
{
id: mainView
anchors.fill: parent
states:
[
State
{
name: "waiting_account_select"
PropertyChanges { target: swipeView; currentIndex: 0 }
PropertyChanges { target: locationsTab; enabled: true }
},
State
{
name: "running_ok"
PropertyChanges { target: swipeView; currentIndex: 1 }
PropertyChanges { target: locationsTab; enabled: false }
},
State
{
name: "running_ok_no_full_control"
PropertyChanges { target: swipeView; currentIndex: 1 }
PropertyChanges { target: locationsTab; enabled: false }
}
]
LibresapiLocalClient
{
onGoodResponseReceived:
{
var jsonReponse = JSON.parse(msg)
mainView.state = jsonReponse.data.runstate
}
Component.onCompleted:
{
openConnection(apiSocketPath)
request("/control/runstate/", "")
}
}
TabView
{
id: swipeView
anchors.fill: parent
visible: true
currentIndex: 0
Tab
{
title:"Locations"
id: locationsTab
Locations { onVisibleChanged: focus = visible }
}
Tab
{
title: "Trusted Nodes"
TrustedNodesView { onVisibleChanged: focus = visible }
}
Tab
{
title: "Contacts"
Contacts { onVisibleChanged: focus = visible }
}
Tab
{
title: "Add Node"
AddTrustedNode { onVisibleChanged: focus = visible }
}
Tab
{
title: "Blue"
Rectangle { color: "blue"; anchors.fill: parent }
}
}
}
/*
onSceneGraphInitialized: llc.openConnection()
Rectangle {
id: page
width: 600; height: 400
color: "#336699" // "#FFFFFF"
Rectangle {
id: header
width: parent.width
anchors.top: parent.top
anchors.left: parent.left
height: 50
ApplicationBar {
id: status
AppButton {
icon: "icons/contacts-128.png"
onButtonClicked : {
tabView.currentIndex = 0
}
}
AppButton {
icon: "icons/settings-4-128.png"
onButtonClicked : {
tabView.currentIndex = 1
}
}
AppButton {
icon: "icons/email-128.png"
onButtonClicked : {
tabView.currentIndex = 2
}
}
AppButton {
icon: "icons/star-2-128.png"
onButtonClicked : {
tabView.currentIndex = 3
}
}
}
}
TabView {
id: tabView
width: parent.width
anchors.top: header.bottom
anchors.left: parent.left
anchors.bottom: parent.bottom
tabsVisible: false
Tab {
id: gxsIds
//onActiveChanged: llc.request("/identity/", "")
onVisibleChanged: llc.request("/identity/", "")
GxsService {
id: gxss
title: "Friends"
// Button {
// text: "buto"
// anchors.left: gxss.right
// onClicked: {
// // gxss.title = "provaboba"
// // gxss.title = llc.request("/identity/", "")
// //llc.request("/identity/", "") // canviar per onVisibleChanged de Tab potser
// }
// }
Connections {
target: llc
onGoodResponseReceived: gxss.title = msg //console.log("Image has changed!")
}
//groupDelegate: GxsIdDelegate {}
//groupModel: gxsIdModel
}
}
Tab {
id: forum
GxsService {
id: gxssforum
title: "Forums"
onVisibleChanged: llc.request("/control/locations/", "")
Connections {
target: llc
onGoodResponseReceived: gxssforum.title = msg //console.log("Image has changed!")
}
// This one uses the default GxsGroupDelegate.
// groupModel: forumGroupModel
// msgDelegate: ForumMsgDelegate {}
// msgModel: forumMsgModel
}
}
Tab {
id: channelLinks
GxsService {
title: "Channels"
// custom GroupDelegate.
// groupDelegate: ChannelGroupDelegate {}
// groupModel: channelGroupModel
// msgDelegate: ChannelMsgDelegate {}
// msgModel: channelMsgModel
}
}
Tab {
id: postedLinks
GxsService {
title: "Posted"
// This one uses the default GxsGroupDelegate.
// groupModel: postedGroupModel
// msgDelegate: PostedMsgDelegate {}
// msgModel: postedMsgModel
}
}
}
}
*/
}

View File

@ -0,0 +1,36 @@
!include("../../retroshare.pri"): error("Could not include file ../../retroshare.pri")
QT += qml quick
CONFIG += c++11
SOURCES += main.cpp \
libresapilocalclient.cpp
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Default rules for deployment.
include(deployment.pri)
DISTFILES += \
android/AndroidManifest.xml \
android/gradle/wrapper/gradle-wrapper.jar \
android/gradlew \
android/res/values/libs.xml \
android/build.gradle \
android/gradle/wrapper/gradle-wrapper.properties \
android/gradlew.bat
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
DEPENDPATH *= ../../libretroshare/src
INCLUDEPATH *= ../../libretroshare/src
PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a
LIBS *= ../../libretroshare/src/lib/libretroshare.a
HEADERS += \
libresapilocalclient.h \
debugutils.h

View File

@ -1,12 +1,44 @@
# To {dis,en}able libresapi via local socket (unix domain socket or windows named pipes)
# {,un}comment the following line
#CONFIG *= libresapilocalserver
# To disable RetroShare-gui append the following
# assignation to qmake command line "CONFIG+=no_retroshare_gui"
CONFIG *= retroshare_gui
no_retroshare_gui:CONFIG -= retroshare_gui
# To {dis,en}able libresapi via HTTP (libmicrohttpd) {,un}comment the following line
# To disable RetroShare-nogui append the following
# assignation to qmake command line "CONFIG+=no_retroshare_nogui"
CONFIG *= retroshare_nogui
no_retroshare_nogui:CONFIG -= retroshare_nogui
# To disable RetroShare plugins append the following
# assignation to qmake command line "CONFIG+=no_retroshare_plugins"
CONFIG *= retroshare_plugins
no_retroshare_plugins:CONFIG -= retroshare_plugins
# To enable RetroShare-android-service append the following assignation to
# qmake command line "CONFIG+=retroshare_android_service"
CONFIG *= no_retroshare_android_service
retroshare_android_service:CONFIG -= no_retroshare_android_service
# To enable libresapi via local socket (unix domain socket or windows named
# pipes) append the following assignation to qmake command line
#"CONFIG+=libresapilocalserver"
CONFIG *= no_libresapilocalserver
libresapilocalserver:CONFIG -= no_libresapilocalserver
# To disable libresapi via HTTP (based on libmicrohttpd) append the following
# assignation to qmake command line "CONFIG+=no_libresapihttpserver"
CONFIG *= libresapihttpserver
no_libresapihttpserver:CONFIG -= libresapihttpserver
# To disable SQLCipher support append the following assignation to qmake
# command line "CONFIG+=no_sqlcipher"
CONFIG *= sqlcipher
no_sqlcipher:CONFIG -= sqlcipher
# To disable GXS (General eXchange System) append the following
# assignation to qmake command line "CONFIG+=no_rs_gxs"
CONFIG *= rs_gxs
no_rs_gxs:CONFIG -= rs_gxs
# Gxs is always enabled now.
DEFINES *= RS_ENABLE_GXS
unix {
isEmpty(PREFIX) { PREFIX = "/usr" }
@ -18,22 +50,21 @@ unix {
}
android-g++ {
DEFINES *= NO_SQLCIPHER
CONFIG *= no_libresapihttpserver no_sqlcipher upnp_libupnp
CONFIG -= libresapihttpserver sqlcipher upnp_miniupnpc
QT *= androidextras
DEFINES *= "fopen64=fopen"
DEFINES *= "fseeko64=fseeko"
DEFINES *= "ftello64=ftello"
INCLUDEPATH *= $$NDK_TOOLCHAIN_PATH/sysroot/usr/include/
INCLUDEPATH += $$NDK_TOOLCHAIN_PATH/sysroot/usr/include
LIBS *= -L$$NDK_TOOLCHAIN_PATH/sysroot/usr/lib/
LIBS *= -lssl -lcrypto -lsqlite3 -lupnp -lixml
ANDROID_EXTRA_LIBS *= $$NDK_TOOLCHAIN_PATH/sysroot/usr/lib/libcrypto.so
ANDROID_EXTRA_LIBS *= $$NDK_TOOLCHAIN_PATH/sysroot/usr/lib/libssl.so
ANDROID_EXTRA_LIBS *= $$NDK_TOOLCHAIN_PATH/sysroot/usr/lib/libbz2.so
LIBS *= -lbz2 -lupnp -lixml -lthreadutil -lsqlite3
ANDROID_EXTRA_LIBS *= $$NDK_TOOLCHAIN_PATH/sysroot/usr/lib/libsqlite3.so
ANDROID_EXTRA_LIBS *= $$NDK_TOOLCHAIN_PATH/sysroot/usr/lib/libupnp.so
ANDROID_EXTRA_LIBS *= $$NDK_TOOLCHAIN_PATH/sysroot/usr/lib/libixml.so
message(NDK_TOOLCHAIN_PATH: $$NDK_TOOLCHAIN_PATH)
message(LIBS: $$LIBS)
message(ANDROID_EXTRA_LIBS: $$ANDROID_EXTRA_LIBS)
# message(LIBS: $$LIBS)
# message(ANDROID_EXTRA_LIBS: $$ANDROID_EXTRA_LIBS)
# message(ANDROID_PLATFORM: $$ANDROID_PLATFORM)
# message(ANDROID_PLATFORM_ROOT_PATH: $$ANDROID_PLATFORM_ROOT_PATH)
# message(NDK_TOOLCHAIN_PATH: $$NDK_TOOLCHAIN_PATH)
}
win32 {
@ -95,6 +126,8 @@ unfinished {
}
wikipoos:DEFINES *= RS_USE_WIKI
rs_gxs:DEFINES *= RS_ENABLE_GXS
libresapilocalserver:DEFINES *= LIBRESAPI_LOCAL_SERVER
libresapihttpserver::DEFINES *= ENABLE_WEBUI
libresapihttpserver:DEFINES *= ENABLE_WEBUI
sqlcipher:DEFINES -= NO_SQLCIPHER
no_sqlcipher:DEFINES *= NO_SQLCIPHER

View File

@ -47,7 +47,7 @@ linux-* {
#LIBS += ../../supportlibs/pegmarkdown/lib/libpegmarkdown.a
contains(CONFIG, NO_SQLCIPHER) {
no_sqlcipher {
DEFINES *= NO_SQLCIPHER
PKGCONFIG *= sqlite3
} else {