Merge branch 'master' into merge_alpha_master

This commit is contained in:
Gioacchino Mazzurco 2017-04-18 21:30:25 +02:00
commit 4455bfa92d
110 changed files with 2395 additions and 629 deletions

View file

@ -2,7 +2,7 @@ Source: retroshare06
Section: devel Section: devel
Priority: standard Priority: standard
Maintainer: Cyril Soler <csoler@users.sourceforge.net> Maintainer: Cyril Soler <csoler@users.sourceforge.net>
Build-Depends: debhelper (>= 7), libglib2.0-dev, libupnp-dev, libssl-dev, libxss-dev, libgnome-keyring-dev, libbz2-dev, libspeex-dev, libspeexdsp-dev, libxslt1-dev, cmake, libcurl4-openssl-dev, libopencv-dev, tcl8.6, libsqlcipher-dev, libmicrohttpd-dev, libavcodec-dev, qtmultimedia5-dev, qttools5-dev, libqt5x11extras5-dev, qt5-default Build-Depends: debhelper (>= 7), libglib2.0-dev, libupnp-dev, libssl-dev, libxss-dev, libgnome-keyring-dev, libbz2-dev, libspeex-dev, libspeexdsp-dev, libxslt1-dev, cmake, libcurl4-openssl-dev, libopencv-dev, tcl8.6, libsqlcipher-dev (>= 3.4.0), libmicrohttpd-dev, libavcodec-dev, qtmultimedia5-dev, qttools5-dev, libqt5x11extras5-dev, qt5-default
Standards-Version: 3.9.6 Standards-Version: 3.9.6
Homepage: http://retroshare.sourceforge.net Homepage: http://retroshare.sourceforge.net

View file

@ -4,6 +4,7 @@
version="0.6.2" version="0.6.2"
gitpath="https://github.com/RetroShare/RetroShare.git" gitpath="https://github.com/RetroShare/RetroShare.git"
workdir=retroshare06-${version} workdir=retroshare06-${version}
branch="v0.6.2-official_release"
#bubba3="Y" # comment out to compile for bubba3 #bubba3="Y" # comment out to compile for bubba3
###################################################### ######################################################
@ -66,6 +67,7 @@ echo " "Commit count : ${ccount}
echo " "Date : ${date} echo " "Date : ${date}
echo " "Time : ${time} echo " "Time : ${time}
echo " "Hash : ${hhsh} echo " "Hash : ${hhsh}
echo " "Using branch : ${branch}
echo " "Using revision : ${rev} echo " "Using revision : ${rev}
echo Done. echo Done.
@ -80,7 +82,7 @@ echo Extracting base archive...
mkdir -p ${workdir}/src mkdir -p ${workdir}/src
echo Checking out latest snapshot... echo Checking out latest snapshot...
cd ${workdir}/src cd ${workdir}/src
git clone --depth 1 https://github.com/RetroShare/RetroShare.git . git clone --depth 1 https://github.com/RetroShare/RetroShare.git --single-branch --branch $branch .
cd - cd -
if ! test -d ${workdir}/src/libretroshare/; then if ! test -d ${workdir}/src/libretroshare/; then

View file

@ -58,7 +58,7 @@
/*************************************/ /*************************************/
UdpBitDht::UdpBitDht(UdpPublisher *pub, bdNodeId *id, std::string appVersion, std::string bootstrapfile, const std::string& filteredipfile, bdDhtFunctions *fns) UdpBitDht::UdpBitDht(UdpPublisher *pub, bdNodeId *id, std::string appVersion, std::string bootstrapfile, const std::string& filteredipfile, bdDhtFunctions *fns)
:UdpSubReceiver(pub), dhtMtx(true), mFns(fns) :UdpSubReceiver(pub), dhtMtx(true)//, mFns(fns)
{ {
std::string usedVersion; std::string usedVersion;

View file

@ -119,7 +119,7 @@ void clearDataTransferred();
bdMutex dhtMtx; /* for all class data (below) */ bdMutex dhtMtx; /* for all class data (below) */
bdNodeManager *mBitDhtManager; bdNodeManager *mBitDhtManager;
bdDhtFunctions *mFns; //bdDhtFunctions *mFns;
uint32_t mReadBytes; uint32_t mReadBytes;

View file

@ -103,8 +103,6 @@ int bdnet_inet_aton(const char *name, struct in_addr *addr);
int bdnet_checkTTL(int fd); int bdnet_checkTTL(int fd);
void bdsockaddr_clear(struct sockaddr_in *addr); void bdsockaddr_clear(struct sockaddr_in *addr);
/* thread-safe version of inet_ntoa */
std::string bdnet_inet_ntoa(struct in_addr in);
/* Extra stuff to declare for windows error handling (mimics unix errno) /* Extra stuff to declare for windows error handling (mimics unix errno)
*/ */
@ -175,4 +173,7 @@ int usleep(unsigned int usec);
} /* C Interface */ } /* C Interface */
#endif #endif
/* thread-safe version of inet_ntoa */
std::string bdnet_inet_ntoa(struct in_addr in);
#endif /* BITDHT_UNIVERSAL_NETWORK_HEADER */ #endif /* BITDHT_UNIVERSAL_NETWORK_HEADER */

View file

@ -17,6 +17,10 @@
#include "ChannelsHandler.h" #include "ChannelsHandler.h"
#include "StatsHandler.h" #include "StatsHandler.h"
#ifdef LIBRESAPI_QT
#include "SettingsHandler.h"
#endif
/* /*
data types in json http://json.org/ data types in json http://json.org/
string (utf-8 unicode) string (utf-8 unicode)
@ -237,6 +241,9 @@ public:
mApiPluginHandler(sts, ifaces), mApiPluginHandler(sts, ifaces),
mChannelsHandler(ifaces.mGxsChannels), mChannelsHandler(ifaces.mGxsChannels),
mStatsHandler() mStatsHandler()
#ifdef LIBRESAPI_QT
,mSettingsHandler(sts)
#endif
{ {
// the dynamic cast is to not confuse the addResourceHandler template like this: // the dynamic cast is to not confuse the addResourceHandler template like this:
// addResourceHandler(derived class, parent class) // addResourceHandler(derived class, parent class)
@ -262,7 +269,11 @@ public:
&ChannelsHandler::handleRequest); &ChannelsHandler::handleRequest);
router.addResourceHandler("stats", dynamic_cast<ResourceRouter*>(&mStatsHandler), router.addResourceHandler("stats", dynamic_cast<ResourceRouter*>(&mStatsHandler),
&StatsHandler::handleRequest); &StatsHandler::handleRequest);
} #ifdef LIBRESAPI_QT
router.addResourceHandler("settings", dynamic_cast<ResourceRouter*>(&mSettingsHandler),
&SettingsHandler::handleRequest);
#endif
}
PeersHandler mPeersHandler; PeersHandler mPeersHandler;
IdentityHandler mIdentityHandler; IdentityHandler mIdentityHandler;
@ -274,6 +285,10 @@ public:
ApiPluginHandler mApiPluginHandler; ApiPluginHandler mApiPluginHandler;
ChannelsHandler mChannelsHandler; ChannelsHandler mChannelsHandler;
StatsHandler mStatsHandler; StatsHandler mStatsHandler;
#ifdef LIBRESAPI_QT
SettingsHandler mSettingsHandler;
#endif
}; };
ApiServer::ApiServer(): ApiServer::ApiServer():
@ -362,6 +377,9 @@ std::string ApiServer::handleRequest(Request &request)
if(data.isRawData()) if(data.isRawData())
return data.getRawData(); return data.getRawData();
if(!resp.mCallbackName.empty())
outstream << resource_api::makeKeyValueReference("callback_name", resp.mCallbackName);
outstream << resource_api::makeKeyValue("debug_msg", debugString.str()); outstream << resource_api::makeKeyValue("debug_msg", debugString.str());
outstream << resource_api::makeKeyValueReference("returncode", returncode); outstream << resource_api::makeKeyValueReference("returncode", returncode);
if(!resp.mStateToken.isNull()) if(!resp.mStateToken.isNull())

View file

@ -252,6 +252,9 @@ public:
StateToken mStateToken; StateToken mStateToken;
//Just for GUI benefit
std::string mCallbackName;
// the result // the result
StreamBase& mDataStream; StreamBase& mDataStream;

View file

@ -24,6 +24,7 @@
#include <retroshare/rspeers.h> #include <retroshare/rspeers.h>
#include <retroshare/rsidentity.h> #include <retroshare/rsidentity.h>
#include <retroshare/rshistory.h>
#include <algorithm> #include <algorithm>
#include <limits> #include <limits>
@ -165,6 +166,7 @@ ChatHandler::ChatHandler(StateTokenServer *sts, RsNotify *notify, RsMsgs *msgs,
addResourceHandler("lobbies", this, &ChatHandler::handleLobbies); addResourceHandler("lobbies", this, &ChatHandler::handleLobbies);
addResourceHandler("subscribe_lobby", this, &ChatHandler::handleSubscribeLobby); addResourceHandler("subscribe_lobby", this, &ChatHandler::handleSubscribeLobby);
addResourceHandler("unsubscribe_lobby", this, &ChatHandler::handleUnsubscribeLobby); addResourceHandler("unsubscribe_lobby", this, &ChatHandler::handleUnsubscribeLobby);
addResourceHandler("autosubscribe_lobby", this, &ChatHandler::handleAutoSubsribeLobby);
addResourceHandler("clear_lobby", this, &ChatHandler::handleClearLobby); addResourceHandler("clear_lobby", this, &ChatHandler::handleClearLobby);
addResourceHandler("lobby_participants", this, &ChatHandler::handleLobbyParticipants); addResourceHandler("lobby_participants", this, &ChatHandler::handleLobbyParticipants);
addResourceHandler("messages", this, &ChatHandler::handleMessages); addResourceHandler("messages", this, &ChatHandler::handleMessages);
@ -908,6 +910,15 @@ void ChatHandler::handleUnsubscribeLobby(Request &req, Response &resp)
resp.setOk(); resp.setOk();
} }
void ChatHandler::handleAutoSubsribeLobby(Request& req, Response& resp)
{
ChatLobbyId chatId = 0;
bool autosubsribe;
req.mStream << makeKeyValueReference("chatid", chatId) << makeKeyValueReference("autosubsribe", autosubsribe);
mRsMsgs->setLobbyAutoSubscribe(chatId, autosubsribe);
resp.setOk();
}
void ChatHandler::handleClearLobby(Request &req, Response &resp) void ChatHandler::handleClearLobby(Request &req, Response &resp)
{ {
ChatLobbyId id = 0; ChatLobbyId id = 0;
@ -949,13 +960,14 @@ void ChatHandler::handleMessages(Request &req, Response &resp)
{ {
RS_STACK_MUTEX(mMtx); /********** LOCKED **********/ RS_STACK_MUTEX(mMtx); /********** LOCKED **********/
ChatId id(req.mPath.top()); ChatId id(req.mPath.top());
// make response a list // make response a list
resp.mDataStream.getStreamToMember(); resp.mDataStream.getStreamToMember();
if(id.isNotSet()) if(id.isNotSet())
{ {
resp.setFail("\""+req.mPath.top()+"\" is not a valid chat id"); resp.setFail("\""+req.mPath.top()+"\" is not a valid chat id");
return; return;
} }
std::map<ChatId, std::list<Msg> >::iterator mit = mMsgs.find(id); std::map<ChatId, std::list<Msg> >::iterator mit = mMsgs.find(id);
if(mit == mMsgs.end()) if(mit == mMsgs.end())
@ -992,10 +1004,11 @@ void ChatHandler::handleSendMessage(Request &req, Response &resp)
void ChatHandler::handleMarkChatAsRead(Request &req, Response &resp) void ChatHandler::handleMarkChatAsRead(Request &req, Response &resp)
{ {
RS_STACK_MUTEX(mMtx); /********** LOCKED **********/ RS_STACK_MUTEX(mMtx); /********** LOCKED **********/
ChatId id(req.mPath.top()); ChatId id(req.mPath.top());
if(id.isNotSet()) if(id.isNotSet())
{ {
resp.setFail("\""+req.mPath.top()+"\" is not a valid chat id"); resp.setFail("\""+req.mPath.top()+"\" is not a valid chat id");
return; return;
} }
std::map<ChatId, std::list<Msg> >::iterator mit = mMsgs.find(id); std::map<ChatId, std::list<Msg> >::iterator mit = mMsgs.find(id);

View file

@ -120,6 +120,7 @@ private:
void handleLobbies(Request& req, Response& resp); void handleLobbies(Request& req, Response& resp);
void handleSubscribeLobby(Request& req, Response& resp); void handleSubscribeLobby(Request& req, Response& resp);
void handleUnsubscribeLobby(Request& req, Response& resp); void handleUnsubscribeLobby(Request& req, Response& resp);
void handleAutoSubsribeLobby(Request& req, Response& resp);
void handleClearLobby(Request& req, Response& resp); void handleClearLobby(Request& req, Response& resp);
ResponseTask* handleLobbyParticipants(Request& req, Response& resp); ResponseTask* handleLobbyParticipants(Request& req, Response& resp);
void handleMessages(Request& req, Response& resp); void handleMessages(Request& req, Response& resp);

View file

@ -10,8 +10,8 @@
namespace resource_api namespace resource_api
{ {
FileSearchHandler::FileSearchHandler(StateTokenServer *sts, RsNotify *notify, RsTurtle *turtle, RsFiles *files): FileSearchHandler::FileSearchHandler(StateTokenServer *sts, RsNotify *notify, RsTurtle *turtle, RsFiles */*files*/):
mStateTokenServer(sts), mNotify(notify), mTurtle(turtle), mFiles(files), mStateTokenServer(sts), mNotify(notify), mTurtle(turtle),// mFiles(files),
mMtx("FileSearchHandler") mMtx("FileSearchHandler")
{ {
mNotify->registerNotifyClient(this); mNotify->registerNotifyClient(this);

View file

@ -24,7 +24,7 @@ private:
StateTokenServer* mStateTokenServer; StateTokenServer* mStateTokenServer;
RsNotify* mNotify; RsNotify* mNotify;
RsTurtle* mTurtle; RsTurtle* mTurtle;
RsFiles* mFiles; //RsFiles* mFiles;
class Search{ class Search{
public: public:

View file

@ -103,9 +103,13 @@ IdentityHandler::IdentityHandler(StateTokenServer *sts, RsNotify *notify, RsIden
{ {
mNotify->registerNotifyClient(this); mNotify->registerNotifyClient(this);
addResourceHandler("*", this, &IdentityHandler::handleWildcard); addResourceHandler("*", this, &IdentityHandler::handleWildcard);
addResourceHandler("own", this, &IdentityHandler::handleOwn); addResourceHandler("own", this, &IdentityHandler::handleOwn);
addResourceHandler("create_identity", this, &IdentityHandler::handleCreateIdentity);
addResourceHandler("own_ids", this, &IdentityHandler::handleOwnIdsRequest);
addResourceHandler("notown_ids", this, &IdentityHandler::handleNotOwnIdsRequest);
addResourceHandler("create_identity", this, &IdentityHandler::handleCreateIdentity);
} }
IdentityHandler::~IdentityHandler() IdentityHandler::~IdentityHandler()
@ -178,6 +182,112 @@ void IdentityHandler::handleWildcard(Request & /*req*/, Response &resp)
else resp.setFail(); else resp.setFail();
} }
void IdentityHandler::handleNotOwnIdsRequest(Request & /*req*/, Response &resp)
{
bool ok = true;
{
RS_STACK_MUTEX(mMtx);
resp.mStateToken = mStateToken;
}
RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
uint32_t token;
mRsIdentity->getTokenService()->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts);
time_t start = time(NULL);
while((mRsIdentity->getTokenService()->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
&&(mRsIdentity->getTokenService()->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_FAILED)
&&((time(NULL) < (start+10)))
)
{
#ifdef WINDOWS_SYS
Sleep(500);
#else
usleep(500*1000);
#endif
}
if(mRsIdentity->getTokenService()->requestStatus(token) == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
{
std::vector<RsGxsIdGroup> grps;
ok &= mRsIdentity->getGroupData(token, grps);
for(std::vector<RsGxsIdGroup>::iterator vit = grps.begin(); vit != grps.end(); vit++)
{
RsGxsIdGroup& grp = *vit;
//electron: not very happy about this, i think the flags should stay hidden in rsidentities
if(!(grp.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) && grp.mIsAContact)
{
bool pgp_linked = (grp.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility ) ;
resp.mDataStream.getStreamToMember()
<< makeKeyValueReference("id", grp.mMeta.mGroupId) /// @deprecated using "id" as key can cause problems in some JS based languages like Qml @see gxs_id instead
<< makeKeyValueReference("gxs_id", grp.mMeta.mGroupId)
<< makeKeyValueReference("pgp_id",grp.mPgpId )
<< makeKeyValueReference("name", grp.mMeta.mGroupName)
<< makeKeyValueReference("pgp_linked", pgp_linked);
}
}
}
else ok = false;
if(ok) resp.setOk();
else resp.setFail();
}
void IdentityHandler::handleOwnIdsRequest(Request & /*req*/, Response &resp)
{
bool ok = true;
{
RS_STACK_MUTEX(mMtx);
resp.mStateToken = mStateToken;
}
RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
uint32_t token;
mRsIdentity->getTokenService()->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts);
time_t start = time(NULL);
while((mRsIdentity->getTokenService()->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
&&(mRsIdentity->getTokenService()->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_FAILED)
&&((time(NULL) < (start+10)))
)
{
#ifdef WINDOWS_SYS
Sleep(500);
#else
usleep(500*1000);
#endif
}
if(mRsIdentity->getTokenService()->requestStatus(token) == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
{
std::vector<RsGxsIdGroup> grps;
ok &= mRsIdentity->getGroupData(token, grps);
for(std::vector<RsGxsIdGroup>::iterator vit = grps.begin(); vit != grps.end(); vit++)
{
RsGxsIdGroup& grp = *vit;
//electron: not very happy about this, i think the flags should stay hidden in rsidentities
if(vit->mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN)
{
bool pgp_linked = (grp.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility ) ;
resp.mDataStream.getStreamToMember()
<< makeKeyValueReference("own_gxs_id", grp.mMeta.mGroupId)
<< makeKeyValueReference("pgp_id",grp.mPgpId )
<< makeKeyValueReference("name", grp.mMeta.mGroupName)
<< makeKeyValueReference("pgp_linked", pgp_linked);
}
}
}
else
ok = false;
if(ok) resp.setOk();
else resp.setFail();
}
ResponseTask* IdentityHandler::handleOwn(Request & /* req */, Response &resp) ResponseTask* IdentityHandler::handleOwn(Request & /* req */, Response &resp)
{ {
StateToken state; StateToken state;

View file

@ -23,6 +23,9 @@ public:
private: private:
void handleWildcard(Request& req, Response& resp); void handleWildcard(Request& req, Response& resp);
void handleNotOwnIdsRequest(Request& req, Response& resp);
void handleOwnIdsRequest(Request& req, Response& resp);
ResponseTask *handleOwn(Request& req, Response& resp); ResponseTask *handleOwn(Request& req, Response& resp);
ResponseTask *handleCreateIdentity(Request& req, Response& resp); ResponseTask *handleCreateIdentity(Request& req, Response& resp);

View file

@ -3,6 +3,7 @@
#include <retroshare/rspeers.h> #include <retroshare/rspeers.h>
#include <retroshare/rsmsgs.h> #include <retroshare/rsmsgs.h>
#include <util/radix64.h> #include <util/radix64.h>
#include <retroshare/rsstatus.h>
#include <algorithm> #include <algorithm>
@ -12,6 +13,12 @@
namespace resource_api namespace resource_api
{ {
#define PEER_STATE_ONLINE 1
#define PEER_STATE_BUSY 2
#define PEER_STATE_AWAY 3
#define PEER_STATE_AVAILABLE 4
#define PEER_STATE_INACTIVE 5
#define PEER_STATE_OFFLINE 6
// todo: groups, add friend, remove friend, permissions // todo: groups, add friend, remove friend, permissions
void peerDetailsToStream(StreamBase& stream, RsPeerDetails& details) void peerDetailsToStream(StreamBase& stream, RsPeerDetails& details)
@ -21,7 +28,50 @@ void peerDetailsToStream(StreamBase& stream, RsPeerDetails& details)
<< makeKeyValueReference("name", details.name) << makeKeyValueReference("name", details.name)
<< makeKeyValueReference("location", details.location) << makeKeyValueReference("location", details.location)
<< makeKeyValueReference("pgp_id", details.gpg_id) << makeKeyValueReference("pgp_id", details.gpg_id)
; << makeKeyValueReference("pgp_id", details.gpg_id);
if(details.state & RS_PEER_STATE_CONNECTED)
{
std::list<StatusInfo> statusInfo;
rsStatus->getStatusList(statusInfo);
std::string state_string;
std::list<StatusInfo>::iterator it;
for (it = statusInfo.begin(); it != statusInfo.end(); ++it)
{
if (it->id == details.id)
{
switch (it->status)
{
case RS_STATUS_INACTIVE:
state_string = "inactive";
break;
case RS_STATUS_ONLINE:
state_string = "online";
break;
case RS_STATUS_AWAY:
state_string = "away";
break;
case RS_STATUS_BUSY:
state_string = "busy";
break;
default:
state_string = "undefined";
break;
}
break;
}
}
stream << makeKeyValueReference("state_string", state_string);
}
else
{
std::string state_string = "undefined";
stream << makeKeyValueReference("state_string", state_string);
}
} }
bool peerInfoToStream(StreamBase& stream, RsPeerDetails& details, RsPeers* peers, std::list<RsGroupInfo>& grpInfo, bool have_avatar) bool peerInfoToStream(StreamBase& stream, RsPeerDetails& details, RsPeers* peers, std::list<RsGroupInfo>& grpInfo, bool have_avatar)
@ -29,7 +79,9 @@ bool peerInfoToStream(StreamBase& stream, RsPeerDetails& details, RsPeers* peers
bool ok = true; bool ok = true;
peerDetailsToStream(stream, details); peerDetailsToStream(stream, details);
stream << makeKeyValue("is_online", peers->isOnline(details.id)) stream << makeKeyValue("is_online", peers->isOnline(details.id))
<< makeKeyValue("chat_id", ChatId(details.id).toStdString()); << makeKeyValue("chat_id", ChatId(details.id).toStdString())
<< makeKeyValue("custom_state_string", rsMsgs->getCustomStateString(details.id));
std::string avatar_address = "/"+details.id.toStdString()+"/avatar_image"; std::string avatar_address = "/"+details.id.toStdString()+"/avatar_image";
@ -63,7 +115,13 @@ PeersHandler::PeersHandler(StateTokenServer* sts, RsNotify* notify, RsPeers *pee
mNotify->registerNotifyClient(this); mNotify->registerNotifyClient(this);
mStateTokenServer->registerTickClient(this); mStateTokenServer->registerTickClient(this);
addResourceHandler("*", this, &PeersHandler::handleWildcard); addResourceHandler("*", this, &PeersHandler::handleWildcard);
addResourceHandler("examine_cert", this, &PeersHandler::handleExamineCert); addResourceHandler("get_state_string", this, &PeersHandler::handleGetStateString);
addResourceHandler("set_state_string", this, &PeersHandler::handleSetStateString);
addResourceHandler("get_custom_state_string", this, &PeersHandler::handleGetCustomStateString);
addResourceHandler("set_custom_state_string", this, &PeersHandler::handleSetCustomStateString);
addResourceHandler("get_pgp_options", this, &PeersHandler::handleGetPGPOptions);
addResourceHandler("set_pgp_options", this, &PeersHandler::handleSetPGPOptions);
addResourceHandler("examine_cert", this, &PeersHandler::handleExamineCert);
} }
PeersHandler::~PeersHandler() PeersHandler::~PeersHandler()
@ -100,6 +158,27 @@ void PeersHandler::tick()
mStateTokenServer->discardToken(mStateToken); mStateTokenServer->discardToken(mStateToken);
mStateToken = mStateTokenServer->getNewToken(); mStateToken = mStateTokenServer->getNewToken();
} }
StatusInfo statusInfo;
rsStatus->getOwnStatus(statusInfo);
if(statusInfo.status != status)
{
status = statusInfo.status;
RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/
mStateTokenServer->discardToken(mStringStateToken);
mStringStateToken = mStateTokenServer->getNewToken();
}
std::string custom_state = rsMsgs->getCustomStateString();
if(custom_state != custom_state_string)
{
custom_state_string = custom_state;
RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/
mStateTokenServer->discardToken(mCustomStateToken);
mCustomStateToken = mStateTokenServer->getNewToken();
}
} }
void PeersHandler::notifyUnreadMsgCountChanged(const RsPeerId &peer, uint32_t count) void PeersHandler::notifyUnreadMsgCountChanged(const RsPeerId &peer, uint32_t count)
@ -121,6 +200,73 @@ static bool have_avatar(RsMsgs* msgs, const RsPeerId& id)
return size != 0; return size != 0;
} }
void PeersHandler::handleGetStateString(Request& /*req*/, Response& resp)
{
{
RS_STACK_MUTEX(mMtx);
resp.mStateToken = mStringStateToken;
}
std::string state_string;
StatusInfo statusInfo;
if (rsStatus->getOwnStatus(statusInfo))
{
if(statusInfo.status == RS_STATUS_ONLINE)
state_string = "online";
else if(statusInfo.status == RS_STATUS_BUSY)
state_string = "busy";
else if(statusInfo.status == RS_STATUS_AWAY)
state_string = "away";
else if(statusInfo.status == RS_STATUS_INACTIVE)
state_string = "inactive";
else
state_string = "undefined";
}
else
state_string = "undefined";
resp.mDataStream << makeKeyValueReference("state_string", state_string);
resp.setOk();
}
void PeersHandler::handleSetStateString(Request& req, Response& resp)
{
std::string state_string;
req.mStream << makeKeyValueReference("state_string", state_string);
uint32_t status = RS_STATUS_OFFLINE;
if(state_string == "online")
status = RS_STATUS_ONLINE;
else if(state_string == "busy")
status = RS_STATUS_BUSY;
else if(state_string == "away")
status = RS_STATUS_AWAY;
rsStatus->sendStatus(RsPeerId(), status);
resp.setOk();
}
void PeersHandler::handleGetCustomStateString(Request& /*req*/, Response& resp)
{
{
RS_STACK_MUTEX(mMtx);
resp.mStateToken = mCustomStateToken;
}
std::string custom_state_string = rsMsgs->getCustomStateString();
resp.mDataStream << makeKeyValueReference("custom_state_string", custom_state_string);
resp.setOk();
}
void PeersHandler::handleSetCustomStateString(Request& req, Response& resp)
{
std::string custom_state_string;
req.mStream << makeKeyValueReference("custom_state_string", custom_state_string);
rsMsgs->setCustomStateString(custom_state_string);
resp.setOk();
}
void PeersHandler::handleWildcard(Request &req, Response &resp) void PeersHandler::handleWildcard(Request &req, Response &resp)
{ {
bool ok = false; bool ok = false;
@ -176,6 +322,9 @@ void PeersHandler::handleWildcard(Request &req, Response &resp)
RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/
unread_msgs = mUnreadMsgsCounts; unread_msgs = mUnreadMsgsCounts;
} }
std::list<StatusInfo> statusInfo;
rsStatus->getStatusList(statusInfo);
// list all peers // list all peers
ok = true; ok = true;
std::list<RsPgpId> identities; std::list<RsPgpId> identities;
@ -216,6 +365,11 @@ void PeersHandler::handleWildcard(Request &req, Response &resp)
StreamBase& locationStream = itemStream.getStreamToMember("locations"); StreamBase& locationStream = itemStream.getStreamToMember("locations");
// mark as list (in case list is empty) // mark as list (in case list is empty)
locationStream.getStreamToMember(); locationStream.getStreamToMember();
int bestPeerState = 0;
unsigned int bestRSState = 0;
std::string bestCustomStateString;
for(std::vector<RsPeerDetails>::iterator vit = detailsVec.begin(); vit != detailsVec.end(); ++vit) for(std::vector<RsPeerDetails>::iterator vit = detailsVec.begin(); vit != detailsVec.end(); ++vit)
{ {
if(vit->gpg_id == *lit) if(vit->gpg_id == *lit)
@ -226,8 +380,85 @@ void PeersHandler::handleWildcard(Request &req, Response &resp)
unread = unread_msgs.find(vit->id)->second; unread = unread_msgs.find(vit->id)->second;
stream << makeKeyValueReference("unread_msgs", unread); stream << makeKeyValueReference("unread_msgs", unread);
peerInfoToStream(stream,*vit, mRsPeers, grpInfo, have_avatar(mRsMsgs, vit->id)); peerInfoToStream(stream,*vit, mRsPeers, grpInfo, have_avatar(mRsMsgs, vit->id));
}
/* Custom state string */
std::string customStateString;
if (vit->state & RS_PEER_STATE_CONNECTED)
{
customStateString = rsMsgs->getCustomStateString(vit->id);
}
int peerState = 0;
if (vit->state & RS_PEER_STATE_CONNECTED)
{
// get the status info for this ssl id
int rsState = 0;
std::list<StatusInfo>::iterator it;
for (it = statusInfo.begin(); it != statusInfo.end(); ++it)
{
if (it->id == vit->id)
{
rsState = it->status;
switch (rsState)
{
case RS_STATUS_INACTIVE:
peerState = PEER_STATE_INACTIVE;
break;
case RS_STATUS_ONLINE:
peerState = PEER_STATE_ONLINE;
break;
case RS_STATUS_AWAY:
peerState = PEER_STATE_AWAY;
break;
case RS_STATUS_BUSY:
peerState = PEER_STATE_BUSY;
break;
}
/* find the best ssl contact for the gpg item */
if (bestPeerState == 0 || peerState < bestPeerState)
{
bestPeerState = peerState;
bestRSState = rsState;
bestCustomStateString = customStateString;
}
else if (peerState == bestPeerState)
{
/* equal state */
if (bestCustomStateString.empty() && !customStateString.empty())
{
bestPeerState = peerState;
bestRSState = rsState;
bestCustomStateString = customStateString;
}
}
break;
}
}
}
}
} }
itemStream << makeKeyValue("custom_state_string", bestCustomStateString);
std::string state_string;
if(bestRSState == RS_STATUS_ONLINE)
state_string = "online";
else if(bestRSState == RS_STATUS_BUSY)
state_string = "busy";
else if(bestRSState == RS_STATUS_AWAY)
state_string = "away";
else if(bestRSState == RS_STATUS_INACTIVE)
state_string = "inactive";
else
state_string = "undefined";
itemStream << makeKeyValue("state_string", state_string);
} }
resp.mStateToken = getCurrentStateToken(); resp.mStateToken = getCurrentStateToken();
} }
@ -300,6 +531,120 @@ void PeersHandler::handleExamineCert(Request &req, Response &resp)
} }
} }
void PeersHandler::handleGetPGPOptions(Request& req, Response& resp)
{
std::string pgp_id;
req.mStream << makeKeyValueReference("pgp_id", pgp_id);
RsPgpId pgp(pgp_id);
RsPeerDetails detail;
if(!mRsPeers->getGPGDetails(pgp, detail))
{
resp.setFail();
return;
}
std::string pgp_key = mRsPeers->getPGPKey(detail.gpg_id, false);
resp.mDataStream << makeKeyValue("pgp_fingerprint", detail.fpr.toStdString());
resp.mDataStream << makeKeyValueReference("pgp_key", pgp_key);
resp.mDataStream << makeKeyValue("direct_transfer", detail.service_perm_flags & RS_NODE_PERM_DIRECT_DL);
resp.mDataStream << makeKeyValue("allow_push", detail.service_perm_flags & RS_NODE_PERM_ALLOW_PUSH);
resp.mDataStream << makeKeyValue("require_WL", detail.service_perm_flags & RS_NODE_PERM_REQUIRE_WL);
resp.mDataStream << makeKeyValue("own_sign", detail.ownsign);
resp.mDataStream << makeKeyValue("trustLvl", detail.trustLvl);
uint32_t max_upload_speed = 0;
uint32_t max_download_speed = 0;
mRsPeers->getPeerMaximumRates(pgp, max_upload_speed, max_download_speed);
resp.mDataStream << makeKeyValueReference("maxUploadSpeed", max_upload_speed);
resp.mDataStream << makeKeyValueReference("maxDownloadSpeed", max_download_speed);
StreamBase& signersStream = resp.mDataStream.getStreamToMember("gpg_signers");
// mark as list (in case list is empty)
signersStream.getStreamToMember();
for(std::list<RsPgpId>::const_iterator it(detail.gpgSigners.begin()); it != detail.gpgSigners.end(); ++it)
{
RsPeerDetails detail;
if(!mRsPeers->getGPGDetails(*it, detail))
continue;
std::string pgp_id = (*it).toStdString();
std::string name = detail.name;
signersStream.getStreamToMember()
<< makeKeyValueReference("pgp_id", pgp_id)
<< makeKeyValueReference("name", name);
}
resp.setOk();
}
void PeersHandler::handleSetPGPOptions(Request& req, Response& resp)
{
std::string pgp_id;
req.mStream << makeKeyValueReference("pgp_id", pgp_id);
RsPgpId pgp(pgp_id);
RsPeerDetails detail;
if(!mRsPeers->getGPGDetails(pgp, detail))
{
resp.setFail();
return;
}
int trustLvl;
req.mStream << makeKeyValueReference("trustLvl", trustLvl);
if(trustLvl != (int)detail.trustLvl)
mRsPeers->trustGPGCertificate(pgp, trustLvl);
int max_upload_speed;
int max_download_speed;
req.mStream << makeKeyValueReference("max_upload_speed", max_upload_speed);
req.mStream << makeKeyValueReference("max_download_speed", max_download_speed);
mRsPeers->setPeerMaximumRates(pgp, (uint32_t)max_upload_speed, (uint32_t)max_download_speed);
bool direct_transfer;
bool allow_push;
bool require_WL;
req.mStream << makeKeyValueReference("direct_transfer", direct_transfer);
req.mStream << makeKeyValueReference("allow_push", allow_push);
req.mStream << makeKeyValueReference("require_WL", require_WL);
ServicePermissionFlags flags(0);
if(direct_transfer)
flags = flags | RS_NODE_PERM_DIRECT_DL;
if(allow_push)
flags = flags | RS_NODE_PERM_ALLOW_PUSH;
if(require_WL)
flags = flags | RS_NODE_PERM_REQUIRE_WL;
mRsPeers->setServicePermissionFlags(pgp, flags);
bool own_sign;
req.mStream << makeKeyValueReference("own_sign", own_sign);
if(own_sign)
mRsPeers->signGPGCertificate(pgp);
resp.mStateToken = getCurrentStateToken();
resp.setOk();
}
StateToken PeersHandler::getCurrentStateToken() StateToken PeersHandler::getCurrentStateToken()
{ {
RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/

View file

@ -35,6 +35,15 @@ private:
void handleWildcard(Request& req, Response& resp); void handleWildcard(Request& req, Response& resp);
void handleExamineCert(Request& req, Response& resp); void handleExamineCert(Request& req, Response& resp);
void handleGetStateString(Request& req, Response& resp);
void handleSetStateString(Request& req, Response& resp);
void handleGetCustomStateString(Request& req, Response& resp);
void handleSetCustomStateString(Request& req, Response& resp);
void handleGetPGPOptions(Request& req, Response& resp);
void handleSetPGPOptions(Request& req, Response& resp);
// a helper which ensures proper mutex locking // a helper which ensures proper mutex locking
StateToken getCurrentStateToken(); StateToken getCurrentStateToken();
@ -44,9 +53,14 @@ private:
RsMsgs* mRsMsgs; // required for avatar data RsMsgs* mRsMsgs; // required for avatar data
std::list<RsPeerId> mOnlinePeers; std::list<RsPeerId> mOnlinePeers;
uint32_t status;
std::string custom_state_string;
RsMutex mMtx; RsMutex mMtx;
StateToken mStateToken; // mutex protected StateToken mStateToken; // mutex protected
StateToken mStringStateToken; // mutex protected
StateToken mCustomStateToken; // mutex protected
std::map<RsPeerId, uint32_t> mUnreadMsgsCounts; std::map<RsPeerId, uint32_t> mUnreadMsgsCounts;
}; };
} // namespace resource_api } // namespace resource_api

View file

@ -37,6 +37,13 @@ ResponseTask* ResourceRouter::handleRequest(Request& req, Response& resp)
if(vit->first == req.mPath.top()) if(vit->first == req.mPath.top())
{ {
req.mPath.pop(); req.mPath.pop();
//Just for GUI benefit
std::string callbackName;
req.mStream << makeKeyValueReference("callback_name", callbackName);
resp.mCallbackName = callbackName;
//
return vit->second->handleRequest(req, resp); return vit->second->handleRequest(req, resp);
} }
} }

View file

@ -6,6 +6,7 @@
#include <retroshare/rsinit.h> #include <retroshare/rsinit.h>
#include <retroshare/rsiface.h> #include <retroshare/rsiface.h>
#include <util/rsdir.h>
#include "api/ApiServer.h" #include "api/ApiServer.h"
#include "api/Operators.h" #include "api/Operators.h"
@ -23,7 +24,9 @@ RsControlModule::RsControlModule(int argc, char **argv, StateTokenServer* sts, A
mDataMtx("RsControlModule::mDataMtx"), mDataMtx("RsControlModule::mDataMtx"),
mRunState(WAITING_INIT), mRunState(WAITING_INIT),
mAutoLoginNextTime(false), mAutoLoginNextTime(false),
mWantPassword(false) mWantPassword(false),
mPassword(""),
mPrevIsBad(false)
{ {
mStateToken = sts->getNewToken(); mStateToken = sts->getNewToken();
this->argc = argc; this->argc = argc;
@ -55,13 +58,16 @@ bool RsControlModule::processShouldExit()
return mProcessShouldExit; return mProcessShouldExit;
} }
bool RsControlModule::askForPassword(const std::string &title, const std::string &key_details, bool /* prev_is_bad */, std::string &password, bool& cancelled) bool RsControlModule::askForPassword(const std::string &title, const std::string &key_details, bool prev_is_bad, std::string &password, bool& cancelled)
{ {
cancelled = false ; cancelled = false ;
{ {
RS_STACK_MUTEX(mDataMtx); // ********** LOCKED ********** RS_STACK_MUTEX(mDataMtx); // ********** LOCKED **********
mPrevIsBad = prev_is_bad;
if(mFixedPassword != "") if(mFixedPassword != "")
{ {
password = mFixedPassword; password = mFixedPassword;
return true; return true;
} }
@ -69,25 +75,31 @@ bool RsControlModule::askForPassword(const std::string &title, const std::string
mWantPassword = true; mWantPassword = true;
mTitle = title; mTitle = title;
mKeyName = key_details; mKeyName = key_details;
mPassword = "";
if(mPassword != "")
{
password = mPassword;
mWantPassword = false;
return true;
}
mStateTokenServer->replaceToken(mStateToken); mStateTokenServer->replaceToken(mStateToken);
} }
bool wait = true; int i = 0;
while(wait) while(i<100)
{ {
usleep(5*1000); usleep(5*1000);
RS_STACK_MUTEX(mDataMtx); // ********** LOCKED ********** RS_STACK_MUTEX(mDataMtx); // ********** LOCKED **********
wait = mWantPassword;
if(!wait && mPassword != "") if(mPassword != "")
{ {
password = mPassword; password = mPassword;
mPassword = "";
mWantPassword = false; mWantPassword = false;
mStateTokenServer->replaceToken(mStateToken); mStateTokenServer->replaceToken(mStateToken);
return true; return true;
} }
i++;
} }
return false; return false;
} }
@ -124,6 +136,11 @@ void RsControlModule::run()
bool login_ok = false; bool login_ok = false;
while(!login_ok) while(!login_ok)
{ {
{
RsStackMutex stack(mDataMtx); // ********** LOCKED **********
mPassword = "";
}
// skip account selection if autologin is available // skip account selection if autologin is available
if(initResult != RS_INIT_HAVE_ACCOUNT) if(initResult != RS_INIT_HAVE_ACCOUNT)
setRunState(WAITING_ACCOUNT_SELECT); setRunState(WAITING_ACCOUNT_SELECT);
@ -174,8 +191,19 @@ void RsControlModule::run()
std::cerr << "RsControlModule::run() LockAndLoadCertificates failed. Unexpected switch value: " << retVal << std::endl; std::cerr << "RsControlModule::run() LockAndLoadCertificates failed. Unexpected switch value: " << retVal << std::endl;
break; break;
} }
{
RsStackMutex stack(mDataMtx); // ********** LOCKED **********
mLoadPeerId.clear();
}
} }
{
RsStackMutex stack(mDataMtx); // ********** LOCKED **********
mFixedPassword = mPassword;
mPassword = "";
}
setRunState(WAITING_STARTUP); setRunState(WAITING_STARTUP);
std::cerr << "RsControlModule: login ok, starting Retroshare worker threads..." << std::endl; std::cerr << "RsControlModule: login ok, starting Retroshare worker threads..." << std::endl;
@ -305,7 +333,8 @@ void RsControlModule::handlePassword(Request &req, Response &resp)
resp.mDataStream resp.mDataStream
<< makeKeyValueReference("want_password", mWantPassword) << makeKeyValueReference("want_password", mWantPassword)
<< makeKeyValueReference("key_name", mKeyName); << makeKeyValueReference("key_name", mKeyName)
<< makeKeyValueReference("prev_is_bad", mPrevIsBad);
resp.mStateToken = mStateToken; resp.mStateToken = mStateToken;
resp.setOk(); resp.setOk();
} }
@ -425,17 +454,17 @@ void RsControlModule::handleCreateLocation(Request &req, Response &resp)
RsPeerId ssl_id; RsPeerId ssl_id;
std::string err_string; std::string err_string;
// give the password to the password callback // give the password to the password callback
{ {
RsStackMutex stack(mDataMtx); // ********** LOCKED ********** RsStackMutex stack(mDataMtx); // ********** LOCKED **********
mFixedPassword = pgp_password; mFixedPassword = pgp_password;
} }
bool ssl_ok = RsAccounts::GenerateSSLCertificate(pgp_id, "", ssl_name, "", hidden_port!=0, ssl_password, ssl_id, err_string); bool ssl_ok = RsAccounts::GenerateSSLCertificate(pgp_id, "", ssl_name, "", hidden_port!=0, ssl_password, ssl_id, err_string);
// clear fixed password to restore normal password operation // clear fixed password to restore normal password operation
{ // {
RsStackMutex stack(mDataMtx); // ********** LOCKED ********** // RsStackMutex stack(mDataMtx); // ********** LOCKED **********
mFixedPassword = ""; // mFixedPassword = "";
} // }
if (ssl_ok) if (ssl_ok)
{ {
@ -456,6 +485,20 @@ void RsControlModule::handleCreateLocation(Request &req, Response &resp)
resp.setFail("could not create a new location. Error: "+err_string); resp.setFail("could not create a new location. Error: "+err_string);
} }
bool RsControlModule::askForDeferredSelfSignature(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen,int& signature_result, std::string reason /*=""*/)
{
if(rsPeers->gpgSignData(data,len,sign,signlen,reason))
{
signature_result = SELF_SIGNATURE_RESULT_SUCCESS;
return true;
}
else
{
signature_result = SELF_SIGNATURE_RESULT_FAILED;
return false;
}
}
void RsControlModule::setRunState(RunState s, std::string errstr) void RsControlModule::setRunState(RunState s, std::string errstr)
{ {
RsStackMutex stack(mDataMtx); // ********** LOCKED ********** RsStackMutex stack(mDataMtx); // ********** LOCKED **********

View file

@ -31,8 +31,9 @@ public:
// returns true if the process should terminate // returns true if the process should terminate
bool processShouldExit(); bool processShouldExit();
// from NotifyClient // from NotifyClient
virtual bool askForPassword(const std::string &title, const std::string& key_details, bool prev_is_bad , std::string& password,bool& canceled); virtual bool askForPassword(const std::string &title, const std::string& key_details, bool prev_is_bad , std::string& password,bool& canceled) override;
virtual bool askForDeferredSelfSignature(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen,int& signature_result, std::string reason = "") override;
protected: protected:
// from RsThread // from RsThread
@ -76,6 +77,7 @@ private:
// to notify that a password callback is waiting // to notify that a password callback is waiting
// to answer the request, clear the flag and set the password // to answer the request, clear the flag and set the password
bool mWantPassword; bool mWantPassword;
bool mPrevIsBad;
std::string mTitle; std::string mTitle;
std::string mKeyName; std::string mKeyName;
std::string mPassword; std::string mPassword;

View file

@ -0,0 +1,182 @@
#include "SettingsHandler.h"
#include <iostream>
#include <retroshare/rsinit.h>
namespace resource_api
{
#define SETTINGS_FILE (QString::fromUtf8(RsAccounts::AccountDirectory().c_str()) + "/Sonet.conf")
SettingsHandler::SettingsHandler(StateTokenServer *sts, const QString settingsGroup) :
QSettings(SETTINGS_FILE, QSettings::IniFormat),
mStateTokenServer(sts),
mMtx("SettingsHandler Mutex"),
mStateToken(sts->getNewToken())
{
RsPeerId sPreferedId;
m_bValid = RsAccounts::GetPreferredAccountId(sPreferedId);
if (!settingsGroup.isEmpty())
beginGroup(settingsGroup);
addResourceHandler("*", this, &SettingsHandler::handleSettingsRequest);
addResourceHandler("get_advanced_mode", this, &SettingsHandler::handleGetAdvancedMode);
addResourceHandler("set_advanced_mode", this, &SettingsHandler::handleSetAdvancedMode);
addResourceHandler("get_flickable_grid_mode", this, &SettingsHandler::handleGetFlickableGridMode);
addResourceHandler("set_flickable_grid_mode", this, &SettingsHandler::handleSetFlickableGridMode);
addResourceHandler("get_auto_login", this, &SettingsHandler::handleGetAutoLogin);
addResourceHandler("set_auto_login", this, &SettingsHandler::handleSetAutoLogin);
}
SettingsHandler::~SettingsHandler()
{
sync();
}
void SettingsHandler::handleSettingsRequest(Request &/*req*/, Response &resp)
{
}
void SettingsHandler::handleGetAdvancedMode(Request &/*req*/, Response &resp)
{
{
RS_STACK_MUTEX(mMtx);
resp.mStateToken = mStateToken;
}
bool advanced_mode = valueFromGroup("General", "Advanced", false).toBool();
resp.mDataStream << makeKeyValueReference("advanced_mode", advanced_mode);
resp.setOk();
sync();
}
void SettingsHandler::handleSetAdvancedMode(Request &req, Response &resp)
{
{
RS_STACK_MUTEX(mMtx);
resp.mStateToken = mStateToken;
}
bool advanced_mode;
req.mStream << makeKeyValueReference("advanced_mode", advanced_mode);
setValueToGroup("General", "Advanced", advanced_mode);
resp.setOk();
sync();
}
void SettingsHandler::handleGetFlickableGridMode(Request &/*req*/, Response &resp)
{
{
RS_STACK_MUTEX(mMtx);
resp.mStateToken = mStateToken;
}
bool flickable_grid_mode = valueFromGroup("General", "FlickableGrid", false).toBool();
resp.mDataStream << makeKeyValueReference("flickable_grid_mode", flickable_grid_mode);
resp.setOk();
sync();
}
void SettingsHandler::handleSetFlickableGridMode(Request &req, Response &resp)
{
{
RS_STACK_MUTEX(mMtx);
resp.mStateToken = mStateToken;
}
bool flickable_grid_mode;
req.mStream << makeKeyValueReference("flickable_grid_mode", flickable_grid_mode);
setValueToGroup("General", "FlickableGrid", flickable_grid_mode);
resp.setOk();
sync();
}
void SettingsHandler::handleGetAutoLogin(Request &/*req*/, Response &resp)
{
{
RS_STACK_MUTEX(mMtx);
resp.mStateToken = mStateToken;
}
bool autoLogin = RsInit::getAutoLogin();;
resp.mDataStream << makeKeyValueReference("auto_login", autoLogin);
resp.setOk();
sync();
}
void SettingsHandler::handleSetAutoLogin(Request &req, Response &resp)
{
{
RS_STACK_MUTEX(mMtx);
resp.mStateToken = mStateToken;
}
bool autoLogin;
req.mStream << makeKeyValueReference("auto_login", autoLogin);
RsInit::setAutoLogin(autoLogin);
resp.setOk();
sync();
}
QVariant SettingsHandler::value(const QString &key, const QVariant &defaultVal) const
{
if (m_bValid == false)
{
return defaultVal.isNull() ? defaultValue(key) : defaultVal;
}
return QSettings::value(key, defaultVal.isNull() ? defaultValue(key) : defaultVal);
}
void SettingsHandler::setValue(const QString &key, const QVariant &val)
{
if (m_bValid == false)
{
std::cerr << "RSettings::setValue() Calling on invalid object, key = " << key.toStdString() << std::endl;
return;
}
if (val == defaultValue(key))
QSettings::remove(key);
else if (val != value(key))
QSettings::setValue(key, val);
}
QVariant SettingsHandler::valueFromGroup(const QString &group, const QString &key, const QVariant &defaultVal)
{
beginGroup(group);
QVariant val = value(key, defaultVal);
endGroup();
return val;
}
void SettingsHandler::setValueToGroup(const QString &group, const QString &key, const QVariant &val)
{
beginGroup(group);
setValue(key, val);
endGroup();
}
void SettingsHandler::setDefault(const QString &key, const QVariant &val)
{
_defaults.insert(key, val);
}
QVariant SettingsHandler::defaultValue(const QString &key) const
{
if (_defaults.contains(key))
return _defaults.value(key);
return QVariant();
}
void SettingsHandler::reset()
{
/* Static method, so we have to create a QSettings object. */
QSettings settings(SETTINGS_FILE, QSettings::IniFormat);
settings.clear();
}
} // namespace resource_api

View file

@ -0,0 +1,59 @@
#ifndef SETTINGSHANDLER_H
#define SETTINGSHANDLER_H
#include <QSettings>
#include <util/rsthreads.h>
#include "ResourceRouter.h"
#include "StateTokenServer.h"
/* Reimplemented class RSettings*/
namespace resource_api
{
class SettingsHandler : public ResourceRouter, public QSettings
{
public:
SettingsHandler(StateTokenServer* sts, const QString group = QString());
~SettingsHandler();
static void reset();
QVariant value(const QString &key,
const QVariant &defaultVal = QVariant()) const;
void setValue(const QString &key, const QVariant &val);
QVariant valueFromGroup(const QString &group, const QString &key,
const QVariant &defaultVal = QVariant());
void setValueToGroup(const QString &group, const QString &key,
const QVariant &val);
protected:
void setDefault(const QString &key, const QVariant &val);
QVariant defaultValue(const QString &key) const;
bool m_bValid;
private:
void handleSettingsRequest(Request& req, Response& resp);
void handleGetAdvancedMode(Request& req, Response& resp);
void handleSetAdvancedMode(Request& req, Response& resp);
void handleGetFlickableGridMode(Request& req, Response& resp);
void handleSetFlickableGridMode(Request& req, Response& resp);
void handleGetAutoLogin(Request& req, Response& resp);
void handleSetAutoLogin(Request& req, Response& resp);
QHash<QString, QVariant> _defaults;
StateTokenServer* mStateTokenServer;
RsMutex mMtx;
StateToken mStateToken; // mutex protected
};
} // namespace resource_api
#endif // SETTINGSHANDLER_H

View file

@ -10,6 +10,40 @@ DESTDIR = lib
INCLUDEPATH += ../../libretroshare/src INCLUDEPATH += ../../libretroshare/src
retroshare_android_service {
win32 {
OBJECTS_DIR = temp/obj
LIBS_DIR = $$PWD/../../libs/lib
LIBS += $$OUT_PWD/../../libretroshare/src/lib/libretroshare.a
LIBS += $$OUT_PWD/../../openpgpsdk/src/lib/libops.a
for(lib, LIB_DIR):LIBS += -L"$$lib"
for(bin, BIN_DIR):LIBS += -L"$$bin"
LIBS += -lssl -lcrypto -lpthread -lminiupnpc -lz -lws2_32
LIBS += -luuid -lole32 -liphlpapi -lcrypt32 -lgdi32
LIBS += -lwinmm
DEFINES *= WINDOWS_SYS WIN32_LEAN_AND_MEAN _USE_32BIT_TIME_T
DEPENDPATH += . $$INC_DIR
INCLUDEPATH += . $$INC_DIR
greaterThan(QT_MAJOR_VERSION, 4) {
# Qt 5
RC_INCLUDEPATH += $$_PRO_FILE_PWD_/../../libretroshare/src
} else {
# Qt 4
QMAKE_RC += --include-dir=$$_PRO_FILE_PWD_/../../libretroshare/src
}
}
DEPENDPATH += . ../../libretroshare/src/
INCLUDEPATH += ../../libretroshare/src/
}
libresapihttpserver { libresapihttpserver {
CONFIG += libmicrohttpd CONFIG += libmicrohttpd
@ -183,3 +217,11 @@ libresapilocalserver {
SOURCES *= api/ApiServerLocal.cpp SOURCES *= api/ApiServerLocal.cpp
HEADERS *= api/ApiServerLocal.h HEADERS *= api/ApiServerLocal.h
} }
qt_dependencies {
CONFIG *= qt
QT *= core
SOURCES += api/SettingsHandler.cpp
HEADERS += api/SettingsHandler.h
}

View file

@ -459,8 +459,12 @@ bool GxsSecurity::validateNxsMsg(const RsNxsMsg& msg, const RsTlvKeySignature& s
msgMeta.signSet.TlvClear(); msgMeta.signSet.TlvClear();
RsGxsMessageId msgId = msgMeta.mMsgId, origMsgId = msgMeta.mOrigMsgId; RsGxsMessageId msgId = msgMeta.mMsgId, origMsgId = msgMeta.mOrigMsgId;
msgMeta.mOrigMsgId.clear();
if(msgMeta.mOrigMsgId == msgMeta.mMsgId) // message is not versionned, then the signature was made with mOrigMsgId==NULL
msgMeta.mOrigMsgId.clear();
msgMeta.mMsgId.clear(); msgMeta.mMsgId.clear();
int signOk = 0 ; int signOk = 0 ;
{ {

View file

@ -1270,6 +1270,58 @@ bool RsGenExchange::getMsgRelatedMeta(const uint32_t &token, GxsMsgRelatedMetaMa
return ok; return ok;
} }
bool RsGenExchange::getSerializedGroupData(const uint32_t &token, RsGxsGroupId& id,unsigned char *& data,uint32_t& size)
{
RS_STACK_MUTEX(mGenMtx) ;
std::list<RsNxsGrp*> nxsGrps;
if(!mDataAccess->getGroupData(token, nxsGrps))
return false ;
if(nxsGrps.size() != 1)
{
std::cerr << "(EE) getSerializedGroupData() got multiple groups in single request. This is unexpected." << std::endl;
for(std::list<RsNxsGrp*>::const_iterator it(nxsGrps.begin());it!=nxsGrps.end();++it)
delete *it ;
return false ;
}
RsNxsGrp *nxs_grp = *(nxsGrps.begin());
size = nxs_grp->serial_size() ;
id = nxs_grp->metaData->mGroupId ;
if(size > 1024*1024 || NULL==(data = (unsigned char *)rs_malloc(size)))
{
std::cerr << "(EE) getSerializedGroupData() cannot allocate mem chunk of size " << size << ". Too big, or no room." << std::endl;
delete nxs_grp ;
return false ;
}
return nxs_grp->serialise(data,size) ;
}
bool RsGenExchange::deserializeGroupData(unsigned char *data,uint32_t size)
{
RS_STACK_MUTEX(mGenMtx) ;
RsItem *item = RsNxsSerialiser(mServType).deserialise(data, &size);
RsNxsGrp *nxs_grp = dynamic_cast<RsNxsGrp*>(item) ;
if(item == NULL)
{
std::cerr << "(EE) RsGenExchange::deserializeGroupData(): cannot deserialise this data. Something's wrong." << std::endl;
delete item ;
return false ;
}
mReceivedGrps.push_back( GxsPendingItem<RsNxsGrp*, RsGxsGroupId>(nxs_grp, nxs_grp->grpId,time(NULL)) );
return true ;
}
bool RsGenExchange::getGroupData(const uint32_t &token, std::vector<RsGxsGrpItem *>& grpItem) bool RsGenExchange::getGroupData(const uint32_t &token, std::vector<RsGxsGrpItem *>& grpItem)
{ {
@ -2135,7 +2187,9 @@ void RsGenExchange::publishMsgs()
if(createOk && validSize) if(createOk && validSize)
{ {
// empty orig msg id means this is the original // empty orig msg id means this is the original
// msg // msg.
// (csoler) Why are we doing this???
if(msg->metaData->mOrigMsgId.isNull()) if(msg->metaData->mOrigMsgId.isNull())
{ {
msg->metaData->mOrigMsgId = msg->metaData->mMsgId; msg->metaData->mOrigMsgId = msg->metaData->mMsgId;

View file

@ -288,6 +288,20 @@ protected:
*/ */
bool getGroupData(const uint32_t &token, std::vector<RsGxsGrpItem*>& grpItem); bool getGroupData(const uint32_t &token, std::vector<RsGxsGrpItem*>& grpItem);
/*!
* \brief getSerializedGroupData
* Retrieves the complete group data serialized into a chunk of memory. This can be useful to
* transfer a full group from one machine to another.
*
* \param token token previously obtained from cache request
* \param data memory chunk allocated (using malloc)
* \param size size of the memory chunk.
* \return
*/
bool getSerializedGroupData(const uint32_t &token, RsGxsGroupId &id, unsigned char *& data, uint32_t& size);
bool deserializeGroupData(unsigned char *data, uint32_t size);
template<class GrpType> template<class GrpType>
bool getGroupDataT(const uint32_t &token, std::vector<GrpType*>& grpItem) bool getGroupDataT(const uint32_t &token, std::vector<GrpType*>& grpItem)
{ {

View file

@ -34,8 +34,8 @@
#include "serialiser/rstlvkeys.h" #include "serialiser/rstlvkeys.h"
#include "serialiser/rsgxsitems.h" #include "serialiser/rsgxsitems.h"
class RsGroupMetaData; struct RsGroupMetaData;
class RsMsgMetaData; struct RsMsgMetaData;
static const uint32_t RS_GXS_GRP_META_DATA_VERSION_ID_0001 = 0x0000 ; // change this, and keep old values if the content changes static const uint32_t RS_GXS_GRP_META_DATA_VERSION_ID_0001 = 0x0000 ; // change this, and keep old values if the content changes
static const uint32_t RS_GXS_GRP_META_DATA_VERSION_ID_0002 = 0xaf01 ; // current API static const uint32_t RS_GXS_GRP_META_DATA_VERSION_ID_0002 = 0xaf01 ; // current API
@ -56,22 +56,22 @@ public:
void clear(); void clear();
void operator =(const RsGroupMetaData& rMeta); void operator =(const RsGroupMetaData& rMeta);
//Sort data in same order than serialiser and deserializer //Sort data in same order than serialiser and deserializer
RsGxsGroupId mGroupId; RsGxsGroupId mGroupId;
RsGxsGroupId mOrigGrpId; RsGxsGroupId mOrigGrpId;
RsGxsGroupId mParentGrpId; RsGxsGroupId mParentGrpId;
std::string mGroupName; std::string mGroupName;
uint32_t mGroupFlags; // GXS_SERV::FLAG_PRIVACY_RESTRICTED | GXS_SERV::FLAG_PRIVACY_PRIVATE | GXS_SERV::FLAG_PRIVACY_PUBLIC uint32_t mGroupFlags; // GXS_SERV::FLAG_PRIVACY_RESTRICTED | GXS_SERV::FLAG_PRIVACY_PRIVATE | GXS_SERV::FLAG_PRIVACY_PUBLIC
uint32_t mPublishTs; uint32_t mPublishTs;
uint32_t mCircleType; uint32_t mCircleType;
uint32_t mAuthenFlags; uint32_t mAuthenFlags;
RsGxsId mAuthorId; RsGxsId mAuthorId;
std::string mServiceString; std::string mServiceString;
RsGxsCircleId mCircleId; RsGxsCircleId mCircleId;
RsTlvKeySignatureSet signSet; RsTlvKeySignatureSet signSet;
RsTlvSecurityKeySet keys; RsTlvSecurityKeySet keys;
uint32_t mSignFlags; uint32_t mSignFlags;
// BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG. // BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG.
@ -103,9 +103,9 @@ public:
void clear(); void clear();
void operator =(const RsMsgMetaData& rMeta); void operator =(const RsMsgMetaData& rMeta);
static int refcount; static int refcount;
//Sort data in same order than serialiser and deserializer //Sort data in same order than serialiser and deserializer
RsGxsGroupId mGroupId; RsGxsGroupId mGroupId;
RsGxsMessageId mMsgId; RsGxsMessageId mMsgId;
RsGxsMessageId mThreadId; RsGxsMessageId mThreadId;
@ -121,7 +121,7 @@ public:
// BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG. // BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG.
// normally READ / UNREAD flags. LOCAL Data. // normally READ / UNREAD flags. LOCAL Data.
std::string mServiceString; std::string mServiceString;
uint32_t mMsgStatus; uint32_t mMsgStatus;
uint32_t mMsgSize; uint32_t mMsgSize;
time_t mChildTs; time_t mChildTs;

View file

@ -75,6 +75,12 @@ bool RsGxsDataAccess::requestGroupInfo(uint32_t &token, uint32_t ansType, const
gir->mGroupIds = groupIds; gir->mGroupIds = groupIds;
req = gir; req = gir;
} }
else if(reqType & GXS_REQUEST_TYPE_GROUP_SERIALIZED_DATA)
{
GroupSerializedDataReq* gir = new GroupSerializedDataReq();
gir->mGroupIds = groupIds;
req = gir;
}
if(req == NULL) if(req == NULL)
{ {
@ -103,34 +109,25 @@ bool RsGxsDataAccess::requestGroupInfo(uint32_t &token, uint32_t ansType, const
uint32_t reqType = opts.mReqType; uint32_t reqType = opts.mReqType;
if(reqType & GXS_REQUEST_TYPE_GROUP_META) if(reqType & GXS_REQUEST_TYPE_GROUP_META)
{ req = new GroupMetaReq();
GroupMetaReq* gmr = new GroupMetaReq();
req = gmr;
}
else if(reqType & GXS_REQUEST_TYPE_GROUP_DATA) else if(reqType & GXS_REQUEST_TYPE_GROUP_DATA)
{ req = new GroupDataReq();
GroupDataReq* gdr = new GroupDataReq();
req = gdr;
}
else if(reqType & GXS_REQUEST_TYPE_GROUP_IDS) else if(reqType & GXS_REQUEST_TYPE_GROUP_IDS)
{ req = new GroupIdReq();
GroupIdReq* gir = new GroupIdReq(); else if(reqType & GXS_REQUEST_TYPE_GROUP_SERIALIZED_DATA)
req = gir; req = new GroupSerializedDataReq();
} else
if(req == NULL)
{ {
std::cerr << "RsGxsDataAccess::requestGroupInfo() request type not recognised, type " std::cerr << "RsGxsDataAccess::requestGroupInfo() request type not recognised, type "
<< reqType << std::endl; << reqType << std::endl;
return false; return false;
}else
{
generateToken(token);
#ifdef DATA_DEBUG
std::cerr << "RsGxsDataAccess::requestGroupInfo() gets Token: " << token << std::endl;
#endif
} }
generateToken(token);
#ifdef DATA_DEBUG
std::cerr << "RsGxsDataAccess::requestGroupInfo() gets Token: " << token << std::endl;
#endif
setReq(req, token, ansType, opts); setReq(req, token, ansType, opts);
storeRequest(req); storeRequest(req);
@ -430,7 +427,16 @@ bool RsGxsDataAccess::getGroupData(const uint32_t& token, std::list<RsNxsGrp*>&
else if(req->status == GXS_REQUEST_V2_STATUS_COMPLETE) else if(req->status == GXS_REQUEST_V2_STATUS_COMPLETE)
{ {
GroupDataReq* gmreq = dynamic_cast<GroupDataReq*>(req); GroupDataReq* gmreq = dynamic_cast<GroupDataReq*>(req);
if(gmreq) GroupSerializedDataReq* gsreq = dynamic_cast<GroupSerializedDataReq*>(req);
if(gsreq)
{
grpData.swap(gsreq->mGroupData);
gsreq->mGroupData.clear();
locked_updateRequestStatus(token, GXS_REQUEST_V2_STATUS_DONE);
}
else if(gmreq)
{ {
grpData.swap(gmreq->mGroupData); grpData.swap(gmreq->mGroupData);
gmreq->mGroupData.clear(); gmreq->mGroupData.clear();
@ -804,6 +810,7 @@ void RsGxsDataAccess::processRequests()
MsgIdReq* mir; MsgIdReq* mir;
MsgRelatedInfoReq* mri; MsgRelatedInfoReq* mri;
GroupStatisticRequest* gsr; GroupStatisticRequest* gsr;
GroupSerializedDataReq* grr;
ServiceStatisticRequest* ssr; ServiceStatisticRequest* ssr;
#ifdef DATA_DEBUG #ifdef DATA_DEBUG
@ -851,6 +858,11 @@ void RsGxsDataAccess::processRequests()
{ {
ok = getServiceStatistic(ssr); ok = getServiceStatistic(ssr);
} }
else if((grr = dynamic_cast<GroupSerializedDataReq*>(req)) != NULL)
{
ok = getGroupSerializedData(grr);
}
else else
{ {
std::cerr << "RsGxsDataAccess::processRequests() Failed to process request, token: " std::cerr << "RsGxsDataAccess::processRequests() Failed to process request, token: "
@ -929,7 +941,30 @@ bool RsGxsDataAccess::getServiceStatistic(const uint32_t &token, GxsServiceStati
return true; return true;
} }
bool RsGxsDataAccess::getGroupSerializedData(GroupSerializedDataReq* req)
{
std::map<RsGxsGroupId, RsNxsGrp*> grpData;
std::list<RsGxsGroupId> grpIdsOut;
getGroupList(req->mGroupIds, req->Options, grpIdsOut);
if(grpIdsOut.empty())
return true;
for(std::list<RsGxsGroupId>::iterator lit = grpIdsOut.begin();lit != grpIdsOut.end();++lit)
grpData[*lit] = NULL;
bool ok = mDataStore->retrieveNxsGrps(grpData, true, true);
req->mGroupData.clear();
std::map<RsGxsGroupId, RsNxsGrp*>::iterator mit = grpData.begin();
for(; mit != grpData.end(); ++mit)
req->mGroupData.push_back(mit->second) ;
return ok;
}
bool RsGxsDataAccess::getGroupData(GroupDataReq* req) bool RsGxsDataAccess::getGroupData(GroupDataReq* req)
{ {
std::map<RsGxsGroupId, RsNxsGrp*> grpData; std::map<RsGxsGroupId, RsNxsGrp*> grpData;

View file

@ -418,6 +418,13 @@ private:
*/ */
bool getGroupStatistic(GroupStatisticRequest* req); bool getGroupStatistic(GroupStatisticRequest* req);
/*!
*
* Attempts to retrieve group data in serialized format
* @param req Request object to satisfy
*/
bool getGroupSerializedData(GroupSerializedDataReq* req);
/*! /*!
* *
* Attempts to service statistic * Attempts to service statistic

View file

@ -1972,7 +1972,7 @@ void RsGxsNetService::updateServerSyncTS()
#endif #endif
// I keep the creation, but the data is not used yet. // I keep the creation, but the data is not used yet.
#warning disabled this, but do we need it? #warning csoler 2016-12-12: Disabled this, but do we need it?
// RsGxsServerMsgUpdate& msui(mServerMsgUpdateMap[grpId]) ; // RsGxsServerMsgUpdate& msui(mServerMsgUpdateMap[grpId]) ;
// (cyril) I'm removing this, because the msgUpdateTS is updated when new messages are received by calling locked_stampMsgServerUpdateTS(). // (cyril) I'm removing this, because the msgUpdateTS is updated when new messages are received by calling locked_stampMsgServerUpdateTS().
@ -3000,7 +3000,7 @@ void RsGxsNetService::locked_genReqGrpTransaction(NxsTransaction* tr)
} }
// FIXTESTS global variable rsReputations not available in unittests! // FIXTESTS global variable rsReputations not available in unittests!
#warning Update the code below to correctly send/recv dependign on reputation #warning csoler 2016-12-23: Update the code below to correctly send/recv dependign on reputation
if(!grpSyncItem->authorId.isNull() && mReputations->overallReputationLevel(grpSyncItem->authorId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE) if(!grpSyncItem->authorId.isNull() && mReputations->overallReputationLevel(grpSyncItem->authorId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
{ {
#ifdef NXS_NET_DEBUG_0 #ifdef NXS_NET_DEBUG_0

View file

@ -45,7 +45,7 @@ bool AuthorPending::getAuthorRep(GixsReputation& rep, const RsGxsId& authorId, c
rep.id = authorId ; rep.id = authorId ;
rep.reputation_level = mRep->overallReputationLevel(authorId); rep.reputation_level = mRep->overallReputationLevel(authorId);
#warning can it happen that reputations do not have the info yet? #warning csoler 2017-01-10: Can it happen that reputations do not have the info yet?
return true ; return true ;
#ifdef TO_BE_REMOVED #ifdef TO_BE_REMOVED
{ {

View file

@ -61,6 +61,12 @@ public:
std::list<RsGxsGroupId> mGroupIds; std::list<RsGxsGroupId> mGroupIds;
std::list<RsGxsGroupId> mGroupIdResult; std::list<RsGxsGroupId> mGroupIdResult;
}; };
class GroupSerializedDataReq : public GxsRequest
{
public:
std::list<RsGxsGroupId> mGroupIds;
std::list<RsNxsGrp*> mGroupData;
};
class GroupDataReq : public GxsRequest class GroupDataReq : public GxsRequest
{ {

View file

@ -1194,7 +1194,7 @@ bool p3GxsTunnelService::locked_sendClearTunnelData(RsGxsTunnelDHPublicKeyItem *
if(gitem->data_bytes == NULL) if(gitem->data_bytes == NULL)
{ {
delete gitem ; delete gitem ;
return NULL ; return false ;
} }
// by convention, we use a IV of 0 for unencrypted data. // by convention, we use a IV of 0 for unencrypted data.
memset(gitem->data_bytes,0,8) ; memset(gitem->data_bytes,0,8) ;

View file

@ -279,7 +279,12 @@ win32 {
CONFIG += upnp_miniupnpc CONFIG += upnp_miniupnpc
LIBS += -lsqlcipher no_sqlcipher {
PKGCONFIG *= sqlite3
LIBS += -lsqlite3
} else {
LIBS += -lsqlcipher
}
DEPENDPATH += . $$INC_DIR DEPENDPATH += . $$INC_DIR
INCLUDEPATH += . $$INC_DIR INCLUDEPATH += . $$INC_DIR

View file

@ -51,9 +51,14 @@ RsPluginManager::RsPluginManager(const RsFileHash &hash)
_allow_all_plugins = false ; _allow_all_plugins = false ;
} }
bool RsPluginManager::loadConfiguration(RsFileHash &loadHash)
{
return p3Config::loadConfiguration(loadHash);
}
void RsPluginManager::loadConfiguration() void RsPluginManager::loadConfiguration()
{ {
RsFileHash dummyHash ; RsFileHash dummyHash;
p3Config::loadConfiguration(dummyHash); p3Config::loadConfiguration(dummyHash);
} }

View file

@ -74,6 +74,7 @@ class RsPluginManager: public RsPluginHandler, public p3Config
// -------------------- Own members -------------------------// // -------------------- Own members -------------------------//
// //
virtual void addConfigurations(p3ConfigMgr *cfgMgr) ; virtual void addConfigurations(p3ConfigMgr *cfgMgr) ;
virtual bool loadConfiguration(RsFileHash &loadHash) ;
virtual void loadConfiguration() ; virtual void loadConfiguration() ;
/*! /*!

View file

@ -92,7 +92,7 @@ dhtPeerEntry::dhtPeerEntry()
return; return;
} }
p3DhtMgr::p3DhtMgr(std::string id, pqiConnectCb *cb) p3DhtMgr::p3DhtMgr(RsPeerId id, pqiConnectCb *cb)
:pqiNetAssistConnect(id, cb), dhtMtx("p3DhtMgr"), mStunRequired(true) :pqiNetAssistConnect(id, cb), dhtMtx("p3DhtMgr"), mStunRequired(true)
{ {
/* setup own entry */ /* setup own entry */
@ -237,13 +237,13 @@ bool p3DhtMgr::setExternalInterface(
/* add / remove peers */ /* add / remove peers */
bool p3DhtMgr::findPeer(std::string id) bool p3DhtMgr::findPeer(const RsPeerId& id)
{ {
RsStackMutex stack(dhtMtx); /***** LOCK MUTEX *****/ RsStackMutex stack(dhtMtx); /***** LOCK MUTEX *****/
mDhtModifications = true; mDhtModifications = true;
std::map<std::string, dhtPeerEntry>::iterator it; std::map<RsPeerId, dhtPeerEntry>::iterator it;
it = peers.find(id); it = peers.find(id);
if (it != peers.end()) if (it != peers.end())
{ {
@ -281,14 +281,14 @@ bool p3DhtMgr::findPeer(std::string id)
return true; return true;
} }
bool p3DhtMgr::dropPeer(std::string id) bool p3DhtMgr::dropPeer(const RsPeerId& id)
{ {
RsStackMutex stack(dhtMtx); /***** LOCK MUTEX *****/ RsStackMutex stack(dhtMtx); /***** LOCK MUTEX *****/
mDhtModifications = true; mDhtModifications = true;
/* once we are connected ... don't worry about them anymore */ /* once we are connected ... don't worry about them anymore */
std::map<std::string, dhtPeerEntry>::iterator it; std::map<RsPeerId, dhtPeerEntry>::iterator it;
it = peers.find(id); it = peers.find(id);
if (it == peers.end()) if (it == peers.end())
{ {
@ -302,14 +302,14 @@ bool p3DhtMgr::dropPeer(std::string id)
} }
/* post DHT key saying we should connect */ /* post DHT key saying we should connect */
bool p3DhtMgr::notifyPeer(std::string id) bool p3DhtMgr::notifyPeer(const RsPeerId& id)
{ {
RsStackMutex stack(dhtMtx); /***** LOCK MUTEX *****/ RsStackMutex stack(dhtMtx); /***** LOCK MUTEX *****/
#ifdef DHT_DEBUG #ifdef DHT_DEBUG
std::cerr << "p3DhtMgr::notifyPeer() " << id << std::endl; std::cerr << "p3DhtMgr::notifyPeer() " << id.toStdString() << std::endl;
#endif #endif
std::map<std::string, dhtPeerEntry>::iterator it; std::map<RsPeerId, dhtPeerEntry>::iterator it;
it = peers.find(id); it = peers.find(id);
if (it == peers.end()) if (it == peers.end())
{ {
@ -333,7 +333,7 @@ bool p3DhtMgr::notifyPeer(std::string id)
#ifdef DHT_LOGS #ifdef DHT_LOGS
{ {
/* Log */ /* Log */
rslog(RSL_WARNING, p3dhtzone, "p3DhtMgr::notifyPeer() Id: " + id + " TO SOON - DROPPING"); rslog(RSL_WARNING, p3dhtzone, "p3DhtMgr::notifyPeer() Id: " + id.toStdString() + " TO SOON - DROPPING");
} }
#endif #endif
@ -352,7 +352,7 @@ bool p3DhtMgr::notifyPeer(std::string id)
#ifdef DHT_LOGS #ifdef DHT_LOGS
{ {
/* Log */ /* Log */
rslog(RSL_WARNING, p3dhtzone, "p3DhtMgr::notifyPeer() Id: " + id + " PEER NOT FOUND - Trigger Search"); rslog(RSL_WARNING, p3dhtzone, "p3DhtMgr::notifyPeer() Id: " + id.toStdString() + " PEER NOT FOUND - Trigger Search");
} }
#endif #endif
it->second.lastTS = 0; it->second.lastTS = 0;
@ -364,14 +364,14 @@ bool p3DhtMgr::notifyPeer(std::string id)
} }
/* extract current peer status */ /* extract current peer status */
bool p3DhtMgr::getPeerStatus(std::string id, bool p3DhtMgr::getPeerStatus(const RsPeerId &id,
struct sockaddr_in &laddr, struct sockaddr_in &laddr,
struct sockaddr_in &raddr, struct sockaddr_in &raddr,
uint32_t &type, uint32_t &state) uint32_t &type, uint32_t &state)
{ {
RsStackMutex stack(dhtMtx); /* LOCK MUTEX */ RsStackMutex stack(dhtMtx); /* LOCK MUTEX */
std::map<std::string, dhtPeerEntry>::iterator it; std::map<RsPeerId, dhtPeerEntry>::iterator it;
it = peers.find(id); it = peers.find(id);
/* ignore OFF peers */ /* ignore OFF peers */
@ -776,7 +776,7 @@ int p3DhtMgr::checkPeerDHTKeys()
dhtMtx.lock(); /* LOCK MUTEX */ dhtMtx.lock(); /* LOCK MUTEX */
/* iterate through and find min time and suitable candidate */ /* iterate through and find min time and suitable candidate */
std::map<std::string, dhtPeerEntry>::iterator it,pit; std::map<RsPeerId, dhtPeerEntry>::iterator it,pit;
time_t now = time(NULL); time_t now = time(NULL);
uint32_t period = 0; uint32_t period = 0;
uint32_t repeatPeriod = 6000; uint32_t repeatPeriod = 6000;
@ -802,7 +802,7 @@ int p3DhtMgr::checkPeerDHTKeys()
period = DHT_CHECK_PERIOD; period = DHT_CHECK_PERIOD;
} }
#ifdef DHT_DEBUG #ifdef DHT_DEBUG
std::cerr << "p3DhtMgr::checkPeerDHTKeys() Peer: " << it->second.id; std::cerr << "p3DhtMgr::checkPeerDHTKeys() Peer: " << it->second.id.toStdString();
std::cerr << " Period: " << period; std::cerr << " Period: " << period;
std::cerr << " Delta: " << delta; std::cerr << " Delta: " << delta;
std::cerr << std::endl; std::cerr << std::endl;
@ -865,7 +865,7 @@ int p3DhtMgr::checkNotifyDHT()
RsStackMutex stack(dhtMtx); /***** LOCK MUTEX *****/ RsStackMutex stack(dhtMtx); /***** LOCK MUTEX *****/
/* iterate through and find min time and suitable candidate */ /* iterate through and find min time and suitable candidate */
std::map<std::string, dhtPeerEntry>::iterator it; std::map<RsPeerId, dhtPeerEntry>::iterator it;
time_t now = time(NULL); time_t now = time(NULL);
int repeatPeriod = DHT_DEFAULT_PERIOD; int repeatPeriod = DHT_DEFAULT_PERIOD;
@ -1015,7 +1015,7 @@ int p3DhtMgr::checkStunState()
if (mDhtState == DHT_STATE_CHECK_PEERS) if (mDhtState == DHT_STATE_CHECK_PEERS)
{ {
/* check that they have all be searched for */ /* check that they have all be searched for */
std::map<std::string, dhtPeerEntry>::iterator it; std::map<RsPeerId, dhtPeerEntry>::iterator it;
for(it = peers.begin(); it != peers.end(); it++) for(it = peers.begin(); it != peers.end(); it++)
{ {
if (it->second.state == DHT_PEER_INIT) if (it->second.state == DHT_PEER_INIT)
@ -1287,7 +1287,7 @@ int p3DhtMgr::status(std::ostream &out)
out << "OWN DETAILS END----------------------------------------" << std::endl; out << "OWN DETAILS END----------------------------------------" << std::endl;
/* now peers states */ /* now peers states */
std::map<std::string, dhtPeerEntry>::iterator it; std::map<RsPeerId, dhtPeerEntry>::iterator it;
out << "PEER DETAILS ------------------------------------------" << std::endl; out << "PEER DETAILS ------------------------------------------" << std::endl;
for(it = peers.begin(); it != peers.end(); it++) for(it = peers.begin(); it != peers.end(); it++)
{ {
@ -1622,15 +1622,13 @@ bool p3DhtMgr::dhtResultNotify(std::string idhash)
std::cerr << "p3DhtMgr::dhtResultNotify() from idhash: "; std::cerr << "p3DhtMgr::dhtResultNotify() from idhash: ";
std::cerr << RsUtil::BinToHex(idhash) << std::endl; std::cerr << RsUtil::BinToHex(idhash) << std::endl;
#endif #endif
std::map<std::string, dhtPeerEntry>::iterator it; std::map<RsPeerId, dhtPeerEntry>::iterator it;
time_t now = time(NULL); time_t now = time(NULL);
/* if notify - we must match on the second hash */ /* if notify - we must match on the second hash */
for(it = peers.begin(); (it != peers.end()) && ((it->second).hash2 != idhash); it++) ; for(it = peers.begin(); (it != peers.end()) && ((it->second).hash2 != idhash); it++) ;
/* update data */ /* update data */
std::string peerid;
/* ignore OFF peers */ /* ignore OFF peers */
if ((it != peers.end()) && (it->second.state != DHT_PEER_OFF)) if ((it != peers.end()) && (it->second.state != DHT_PEER_OFF))
{ {
@ -1677,7 +1675,7 @@ bool p3DhtMgr::dhtResultSearch(std::string idhash,
std::cerr << "p3DhtMgr::dhtResultSearch() for idhash: "; std::cerr << "p3DhtMgr::dhtResultSearch() for idhash: ";
std::cerr << RsUtil::BinToHex(idhash) << std::endl; std::cerr << RsUtil::BinToHex(idhash) << std::endl;
#endif #endif
std::map<std::string, dhtPeerEntry>::iterator it; std::map<RsPeerId, dhtPeerEntry>::iterator it;
bool doCb = false; bool doCb = false;
bool doStun = false; bool doStun = false;
uint32_t stunFlags = 0; uint32_t stunFlags = 0;
@ -1780,7 +1778,7 @@ bool p3DhtMgr::dhtResultSearch(std::string idhash,
void printDhtPeerEntry(dhtPeerEntry *ent, std::ostream &out) void printDhtPeerEntry(dhtPeerEntry *ent, std::ostream &out)
{ {
out << "DhtEntry: ID: " << ent->id; out << "DhtEntry: ID: " << ent->id.toStdString();
out << " State: " << ent->state; out << " State: " << ent->state;
out << " lastTS: " << ent->lastTS; out << " lastTS: " << ent->lastTS;
out << " notifyPending: " << ent->notifyPending; out << " notifyPending: " << ent->notifyPending;

View file

@ -78,7 +78,7 @@ class dhtPeerEntry
public: public:
dhtPeerEntry(); dhtPeerEntry();
std::string id; RsPeerId id;
uint32_t state; uint32_t state;
time_t lastTS; time_t lastTS;
@ -97,7 +97,7 @@ class p3DhtMgr: public pqiNetAssistConnect, public RsThread
/* /*
*/ */
public: public:
p3DhtMgr(std::string id, pqiConnectCb *cb); p3DhtMgr(RsPeerId id, pqiConnectCb *cb);
/********** External DHT Interface ************************ /********** External DHT Interface ************************
* These Functions are the external interface * These Functions are the external interface
@ -121,15 +121,15 @@ virtual bool setExternalInterface(struct sockaddr_in laddr,
struct sockaddr_in raddr, uint32_t type); struct sockaddr_in raddr, uint32_t type);
/* add / remove peers */ /* add / remove peers */
virtual bool findPeer(std::string id); virtual bool findPeer(const RsPeerId& id);
virtual bool dropPeer(std::string id); virtual bool dropPeer(const RsPeerId& id);
/* post DHT key saying we should connect (callback when done) */ /* post DHT key saying we should connect (callback when done) */
virtual bool notifyPeer(std::string id); virtual bool notifyPeer(const RsPeerId& id);
/* extract current peer status */ /* extract current peer status */
virtual bool getPeerStatus(std::string id, virtual bool getPeerStatus(const RsPeerId& id,
struct sockaddr_in &laddr, struct sockaddr_in &raddr, struct sockaddr_in &laddr, struct sockaddr_in &raddr,
uint32_t &type, uint32_t &mode); uint32_t &type, uint32_t &mode);
/* stun */ /* stun */
@ -154,17 +154,17 @@ virtual bool dhtResultBootstrap(std::string idhash);
protected: protected:
/* can block briefly (called only from thread) */ /* can block briefly (called only from thread) */
virtual bool dhtPublish(std::string id, virtual bool dhtPublish(std::string idhash,
struct sockaddr_in &laddr, struct sockaddr_in &laddr,
struct sockaddr_in &raddr, struct sockaddr_in &raddr,
uint32_t type, std::string sign); uint32_t type, std::string sign);
virtual bool dhtNotify(std::string peerid, std::string ownId, virtual bool dhtNotify(std::string idhash, std::string ownIdHash,
std::string sign); std::string sign);
virtual bool dhtSearch(std::string id, uint32_t mode); virtual bool dhtSearch(std::string idhash, uint32_t mode);
virtual bool dhtBootstrap(std::string storehash, std::string ownIdHash, virtual bool dhtBootstrap(std::string idhash, std::string ownIdHash,
std::string sign); /* to publish bootstrap */ std::string sign); /* to publish bootstrap */
@ -232,7 +232,7 @@ std::string randomBootstrapId();
dhtPeerEntry ownEntry; dhtPeerEntry ownEntry;
time_t ownNotifyTS; time_t ownNotifyTS;
std::map<std::string, dhtPeerEntry> peers; std::map<RsPeerId, dhtPeerEntry> peers;
std::list<std::string> stunIds; std::list<std::string> stunIds;
bool mStunRequired; bool mStunRequired;

View file

@ -397,7 +397,7 @@ private:
std::map<RsPeerId,sockaddr_storage> mReportedOwnAddresses ; std::map<RsPeerId,sockaddr_storage> mReportedOwnAddresses ;
std::map<RsNodeGroupId,RsGroupInfo> groupList; std::map<RsNodeGroupId,RsGroupInfo> groupList;
uint32_t lastGroupId; //uint32_t lastGroupId;
std::list<RsItem *> saveCleanupList; /* TEMPORARY LIST WHEN SAVING */ std::list<RsItem *> saveCleanupList; /* TEMPORARY LIST WHEN SAVING */

View file

@ -61,14 +61,20 @@ void pqiConnectCbDummy::peerStatus(const RsPeerId& id, const pqiIpAddrSet &ad
std::cerr << out << std::endl; std::cerr << out << std::endl;
} }
void pqiConnectCbDummy::peerConnectRequest(const RsPeerId& id, void pqiConnectCbDummy::peerConnectRequest(const RsPeerId &id, const sockaddr_storage &raddr
const struct sockaddr_storage &raddr, uint32_t source) , const sockaddr_storage &proxyaddr, const sockaddr_storage &srcaddr
, uint32_t source, uint32_t flags, uint32_t delay, uint32_t bandwidth)
{ {
std::cerr << "pqiConnectCbDummy::peerConnectRequest()"; std::cerr << "pqiConnectCbDummy::peerConnectRequest()";
std::cerr << " id: " << id; std::cerr << " id: " << id;
std::cerr << " raddr: " << sockaddr_storage_tostring(raddr); std::cerr << " raddr: " << sockaddr_storage_tostring(raddr);
std::cerr << " proxyaddr: " << sockaddr_storage_tostring(proxyaddr);
std::cerr << " srcaddr: " << sockaddr_storage_tostring(srcaddr);
std::cerr << " source: " << source; std::cerr << " source: " << source;
std::cerr << std::endl; std::cerr << " flags: " << flags;
std::cerr << " delay: " << delay;
std::cerr << " bandwidth: " << bandwidth;
std::cerr << std::endl;
} }
void pqiMonitor::disconnectPeer(const RsPeerId &/*peer*/) void pqiMonitor::disconnectPeer(const RsPeerId &/*peer*/)

View file

@ -179,8 +179,9 @@ virtual ~pqiConnectCbDummy();
virtual void peerStatus(const RsPeerId& id, const pqiIpAddrSet &addrs, virtual void peerStatus(const RsPeerId& id, const pqiIpAddrSet &addrs,
uint32_t type, uint32_t mode, uint32_t source); uint32_t type, uint32_t mode, uint32_t source);
virtual void peerConnectRequest(const RsPeerId& id, virtual void peerConnectRequest(const RsPeerId& id, const struct sockaddr_storage &raddr,
const struct sockaddr_storage &raddr, uint32_t source); const struct sockaddr_storage &proxyaddr, const struct sockaddr_storage &srcaddr,
uint32_t source, uint32_t flags, uint32_t delay, uint32_t bandwidth);
//virtual void stunStatus(std::string id, const struct sockaddr_storage &raddr, uint32_t type, uint32_t flags); //virtual void stunStatus(std::string id, const struct sockaddr_storage &raddr, uint32_t type, uint32_t flags);
}; };

View file

@ -40,7 +40,7 @@ static struct RsLog::logInfo pqipersonzoneInfo = {RsLog::Default, "pqiperson"};
pqiperson::pqiperson(const RsPeerId& id, pqipersongrp *pg) : pqiperson::pqiperson(const RsPeerId& id, pqipersongrp *pg) :
PQInterface(id), mNotifyMtx("pqiperson-notify"), mPersonMtx("pqiperson"), PQInterface(id), mNotifyMtx("pqiperson-notify"), mPersonMtx("pqiperson"),
active(false), activepqi(NULL), inConnectAttempt(false), waittimes(0), active(false), activepqi(NULL), inConnectAttempt(false),// waittimes(0),
pqipg(pg) {} // TODO: must check id! pqipg(pg) {} // TODO: must check id!
pqiperson::~pqiperson() pqiperson::~pqiperson()

View file

@ -29,6 +29,7 @@
#define MRK_PQI_PERSON_HEADER #define MRK_PQI_PERSON_HEADER
#include <string>
#include "pqi/pqi.h" #include "pqi/pqi.h"
#include "util/rsnet.h" #include "util/rsnet.h"
@ -66,7 +67,7 @@ public:
virtual int reset() { pqistreamer::reset(); return ni->reset(); } virtual int reset() { pqistreamer::reset(); return ni->reset(); }
virtual int disconnect() { return reset() ; } virtual int disconnect() { return reset() ; }
virtual bool connect_parameter(uint32_t type, uint32_t value) { return ni->connect_parameter(type, value);} virtual bool connect_parameter(uint32_t type, uint32_t value) { return ni->connect_parameter(type, value);}
virtual bool connect_parameter(uint32_t type, std::string value) { return ni->connect_parameter(type, value);} virtual bool connect_parameter(uint32_t type, const std::string &value) { return ni->connect_parameter(type, value);}
virtual bool connect_additional_address(uint32_t type, const struct sockaddr_storage &addr) { return ni->connect_additional_address(type, addr); } virtual bool connect_additional_address(uint32_t type, const struct sockaddr_storage &addr) { return ni->connect_additional_address(type, addr); }
virtual int getConnectAddress(struct sockaddr_storage &raddr){ return ni->getConnectAddress(raddr); } virtual int getConnectAddress(struct sockaddr_storage &raddr){ return ni->getConnectAddress(raddr); }
@ -171,7 +172,7 @@ private:
bool active; bool active;
pqiconnect *activepqi; pqiconnect *activepqi;
bool inConnectAttempt; bool inConnectAttempt;
int waittimes; //int waittimes;
time_t lastHeartbeatReceived; // use to track connection failure time_t lastHeartbeatReceived; // use to track connection failure
pqipersongrp *pqipg; /* parent for callback */ pqipersongrp *pqipg; /* parent for callback */
}; };

View file

@ -1009,7 +1009,7 @@ int pqissl::Basic_Connection_Complete()
return -1; return -1;
} }
else if ((err == ECONNREFUSED)) else if (err == ECONNREFUSED)
{ {
rslog(RSL_WARNING, pqisslzone, "pqissl::Basic_Connection_Complete() ECONNREFUSED: cert: " + PeerId().toStdString()); rslog(RSL_WARNING, pqisslzone, "pqissl::Basic_Connection_Complete() ECONNREFUSED: cert: " + PeerId().toStdString());

View file

@ -53,7 +53,7 @@ static const uint32_t PQI_SSLUDP_DEF_CONN_PERIOD = 300; /* 5 minutes? */
/********** PQI SSL UDP STUFF **************************************/ /********** PQI SSL UDP STUFF **************************************/
pqissludp::pqissludp(PQInterface *parent, p3LinkMgr *lm) : pqissludp::pqissludp(PQInterface *parent, p3LinkMgr *lm) :
pqissl(NULL, parent, lm), tou_bio(NULL), listen_checktime(0), pqissl(NULL, parent, lm), tou_bio(NULL),// listen_checktime(0),
mConnectPeriod(PQI_SSLUDP_DEF_CONN_PERIOD), mConnectFlags(0), mConnectPeriod(PQI_SSLUDP_DEF_CONN_PERIOD), mConnectFlags(0),
mConnectBandwidth(0) mConnectBandwidth(0)
{ {

View file

@ -95,7 +95,7 @@ private:
BIO *tou_bio; // specific to ssludp. BIO *tou_bio; // specific to ssludp.
long listen_checktime; //long listen_checktime;
uint32_t mConnectPeriod; uint32_t mConnectPeriod;
uint32_t mConnectFlags; uint32_t mConnectFlags;

View file

@ -627,7 +627,7 @@ bool getX509id(X509 *x509, RsPeerId& xid)
* more randomness * more randomness
*/ */
#warning this is cryptographically horrible. We should do a hash of the public key here!!! #warning csoler 2017-02-19: This is cryptographically horrible. We should do a hash of the public key here!!!
xid = RsPeerId(&signdata[signlen - CERTSIGNLEN]) ; xid = RsPeerId(&signdata[signlen - CERTSIGNLEN]) ;

View file

@ -25,7 +25,7 @@ typedef std::pair<RsGxsGroupId, RsGxsMessageId> RsGxsGrpMsgIdPair;
typedef std::map<RsGxsGrpMsgIdPair, std::vector<RsGxsMessageId> > MsgRelatedIdResult; typedef std::map<RsGxsGrpMsgIdPair, std::vector<RsGxsMessageId> > MsgRelatedIdResult;
typedef std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > GxsMsgReq; typedef std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > GxsMsgReq;
class RsMsgMetaData; struct RsMsgMetaData;
typedef std::map<RsGxsGroupId, std::vector<RsMsgMetaData> > MsgMetaResult; typedef std::map<RsGxsGroupId, std::vector<RsMsgMetaData> > MsgMetaResult;

View file

@ -5,7 +5,7 @@
#include "retroshare/rsgxsifacetypes.h" #include "retroshare/rsgxsifacetypes.h"
#include "retroshare/rstokenservice.h" #include "retroshare/rstokenservice.h"
class RsMsgMetaData ; struct RsMsgMetaData ;
typedef std::map<RsGxsGroupId, std::vector<RsMsgMetaData> > GxsMsgMetaMap; typedef std::map<RsGxsGroupId, std::vector<RsMsgMetaData> > GxsMsgMetaMap;
typedef std::map<RsGxsGrpMsgIdPair, std::vector<RsMsgMetaData> > GxsMsgRelatedMetaMap; typedef std::map<RsGxsGrpMsgIdPair, std::vector<RsMsgMetaData> > GxsMsgRelatedMetaMap;

View file

@ -305,6 +305,9 @@ public:
virtual bool setAsRegularContact(const RsGxsId& id,bool is_a_contact) = 0 ; virtual bool setAsRegularContact(const RsGxsId& id,bool is_a_contact) = 0 ;
virtual bool isARegularContact(const RsGxsId& id) = 0 ; virtual bool isARegularContact(const RsGxsId& id) = 0 ;
virtual bool serialiseIdentityToMemory(const RsGxsId& id,std::string& radix_string)=0;
virtual bool deserialiseIdentityFromMemory(const std::string& radix_string)=0;
/*! /*!
* \brief overallReputationLevel * \brief overallReputationLevel
* Returns the overall reputation level of the supplied identity. See rsreputations.h * Returns the overall reputation level of the supplied identity. See rsreputations.h
@ -319,6 +322,7 @@ public:
*/ */
virtual bool getGroupData(const uint32_t &token, std::vector<RsGxsIdGroup> &groups) = 0; virtual bool getGroupData(const uint32_t &token, std::vector<RsGxsIdGroup> &groups) = 0;
virtual bool getGroupSerializedData(const uint32_t &token, std::map<RsGxsId,std::string>& serialized_groups)=0;
//virtual bool getMsgData(const uint32_t &token, std::vector<RsGxsIdOpinion> &opinions) = 0; //virtual bool getMsgData(const uint32_t &token, std::vector<RsGxsIdOpinion> &opinions) = 0;
}; };

View file

@ -47,6 +47,7 @@
#define GXS_REQUEST_TYPE_GROUP_STATS 0x01600000 #define GXS_REQUEST_TYPE_GROUP_STATS 0x01600000
#define GXS_REQUEST_TYPE_SERVICE_STATS 0x03200000 #define GXS_REQUEST_TYPE_SERVICE_STATS 0x03200000
#define GXS_REQUEST_TYPE_GROUP_SERIALIZED_DATA 0x04000000
// TODO CLEANUP: RS_TOKREQOPT_MSG_* should be an inner enum of RsTokReqOptions // TODO CLEANUP: RS_TOKREQOPT_MSG_* should be an inner enum of RsTokReqOptions

View file

@ -1037,6 +1037,9 @@ bool p3Peers::setProxyServer(const uint32_t type, const std::string &addr_str, c
std::cerr << "(EE) attempt to set proxy server address to something not allowed: " << addr_str << ":" << port << std::endl; std::cerr << "(EE) attempt to set proxy server address to something not allowed: " << addr_str << ":" << port << std::endl;
return false ; return false ;
} }
std::cerr << "Settign proxy server address to " << addr_str << ":" << port << std::endl;
struct sockaddr_storage addr; struct sockaddr_storage addr;
struct sockaddr_in *addrv4p = (struct sockaddr_in *) &addr; struct sockaddr_in *addrv4p = (struct sockaddr_in *) &addr;
addrv4p->sin_family = AF_INET; addrv4p->sin_family = AF_INET;

View file

@ -66,8 +66,8 @@
*/ */
RsBanList *rsBanList = NULL ; RsBanList *rsBanList = NULL ;
p3BanList::p3BanList(p3ServiceControl *sc, p3NetMgr *nm) p3BanList::p3BanList(p3ServiceControl *sc, p3NetMgr */*nm*/)
:p3Service(), mBanMtx("p3BanList"), mServiceCtrl(sc), mNetMgr(nm) :p3Service(), mBanMtx("p3BanList"), mServiceCtrl(sc)//, mNetMgr(nm)
{ {
addSerialType(new RsBanListSerialiser()); addSerialType(new RsBanListSerialiser());

View file

@ -148,7 +148,7 @@ private:
std::map<struct sockaddr_storage, BanListPeer> mWhiteListedRanges; std::map<struct sockaddr_storage, BanListPeer> mWhiteListedRanges;
p3ServiceControl *mServiceCtrl; p3ServiceControl *mServiceCtrl;
p3NetMgr *mNetMgr; //p3NetMgr *mNetMgr;
time_t mLastDhtInfoRequest ; time_t mLastDhtInfoRequest ;
bool mIPFilteringEnabled ; bool mIPFilteringEnabled ;

View file

@ -1035,7 +1035,7 @@ bool p3GxsReputation::setOwnOpinion(const RsGxsId& gxsid, const RsReputations::O
if (rit == mReputations.end()) if (rit == mReputations.end())
{ {
#warning we should set the owner node id here. #warning csoler 2017-01-05: We should set the owner node id here.
mReputations[gxsid] = Reputation(gxsid); mReputations[gxsid] = Reputation(gxsid);
rit = mReputations.find(gxsid); rit = mReputations.find(gxsid);
} }

View file

@ -174,7 +174,7 @@ private:
time_t mLastIdentityFlagsUpdate ; time_t mLastIdentityFlagsUpdate ;
bool mReputationsUpdated; bool mReputationsUpdated;
float mAutoBanIdentitiesLimit ; //float mAutoBanIdentitiesLimit ;
bool mAutoSetPositiveOptionToContacts; bool mAutoSetPositiveOptionToContacts;
p3LinkMgr *mLinkMgr; p3LinkMgr *mLinkMgr;

View file

@ -70,6 +70,8 @@ static const time_t MAX_KEEP_KEYS_SIGNED_KNOWN = 30 * 86400 ; // signed ident
static const uint32_t MAX_DELAY_BEFORE_CLEANING= 1800 ; // clean old keys every 30 mins static const uint32_t MAX_DELAY_BEFORE_CLEANING= 1800 ; // clean old keys every 30 mins
static const uint32_t MAX_SERIALISED_IDENTITY_AGE = 600 ; // after 10 mins, a serialised identity record must be renewed.
RsIdentity *rsIdentity = NULL; RsIdentity *rsIdentity = NULL;
/****** /******
@ -97,13 +99,12 @@ RsIdentity *rsIdentity = NULL;
#define BG_REPUTATION 3 #define BG_REPUTATION 3
#define GXSIDREQ_CACHELOAD 0x0001 #define GXSIDREQ_CACHELOAD 0x0001
#define GXSIDREQ_CACHEOWNIDS 0x0002 #define GXSIDREQ_CACHEOWNIDS 0x0002
#define GXSIDREQ_PGPHASH 0x0010
#define GXSIDREQ_PGPHASH 0x0010 #define GXSIDREQ_RECOGN 0x0020
#define GXSIDREQ_RECOGN 0x0020 #define GXSIDREQ_OPINION 0x0030
#define GXSIDREQ_SERIALIZE_TO_MEMORY 0x0040
#define GXSIDREQ_OPINION 0x0030
#define GXSIDREQ_CACHETEST 0x1000 #define GXSIDREQ_CACHETEST 0x1000
@ -697,6 +698,84 @@ bool p3IdService::getOwnIds(std::list<RsGxsId> &ownIds)
return true ; return true ;
} }
bool p3IdService::serialiseIdentityToMemory(const RsGxsId& id,std::string& radix_string)
{
RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/
// look into cache. If available, return the data. If not, request it.
std::map<RsGxsId,SerialisedIdentityStruct>::const_iterator it = mSerialisedIdentities.find(id);
if(it != mSerialisedIdentities.end())
{
Radix64::encode(it->second.mMem,it->second.mSize,radix_string) ;
if(it->second.mLastUsageTS + MAX_SERIALISED_IDENTITY_AGE > time(NULL))
return true ;
std::cerr << "Identity " << id << " will be re-serialised, because the last record is too old." << std::endl;
}
RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
uint32_t token = 0;
std::list<RsGxsGroupId> groupIds;
groupIds.push_back(RsGxsGroupId(id)) ;
RsGenExchange::getTokenService()->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds);
GxsTokenQueue::queueRequest(token, GXSIDREQ_SERIALIZE_TO_MEMORY);
return false;
}
void p3IdService::handle_get_serialized_grp(uint32_t token)
{
// store the serialized data in cache.
unsigned char *mem = NULL;
uint32_t size;
RsGxsGroupId id ;
if(!RsGenExchange::getSerializedGroupData(token,id, mem,size))
{
std::cerr << "(EE) call to RsGenExchage::getSerializedGroupData() failed." << std::endl;
return ;
}
std::cerr << "Received serialised group from RsGenExchange." << std::endl;
std::map<RsGxsId,SerialisedIdentityStruct>::const_iterator it = mSerialisedIdentities.find(RsGxsId(id));
if(it != mSerialisedIdentities.end())
free(it->second.mMem) ;
SerialisedIdentityStruct s ;
s.mMem = mem ;
s.mSize = size ;
s.mLastUsageTS = time(NULL) ;
mSerialisedIdentities[RsGxsId(id)] = s ;
}
bool p3IdService::deserialiseIdentityFromMemory(const std::string& radix_string)
{
std::vector<uint8_t> mem = Radix64::decode(radix_string) ;
if(mem.empty())
{
std::cerr << "Cannot decode radix string \"" << radix_string << "\"" << std::endl;
return false ;
}
if(!RsGenExchange::deserializeGroupData(mem.data(),mem.size()))
{
std::cerr << "Cannot load identity from radix string \"" << radix_string << "\"" << std::endl;
return false ;
}
return true ;
}
bool p3IdService::createIdentity(uint32_t& token, RsIdentityParameters &params) bool p3IdService::createIdentity(uint32_t& token, RsIdentityParameters &params)
{ {
@ -709,7 +788,7 @@ bool p3IdService::createIdentity(uint32_t& token, RsIdentityParameters &params)
if (params.isPgpLinked) if (params.isPgpLinked)
{ {
#warning Backward compatibility issue to fix here in v0.7.0 #warning csoler 2017-02-07: Backward compatibility issue to fix here in v0.7.0
// This is a hack, because a bad decision led to having RSGXSID_GROUPFLAG_REALID be equal to GXS_SERV::FLAG_PRIVACY_PRIVATE. // This is a hack, because a bad decision led to having RSGXSID_GROUPFLAG_REALID be equal to GXS_SERV::FLAG_PRIVACY_PRIVATE.
// In order to keep backward compatibility, we'll also add the new value // In order to keep backward compatibility, we'll also add the new value
@ -1587,6 +1666,28 @@ bool p3IdService::getGroupData(const uint32_t &token, std::vector<RsGxsIdGroup>
return ok; return ok;
} }
bool p3IdService::getGroupSerializedData(const uint32_t &token, std::map<RsGxsId,std::string>& serialized_groups)
{
unsigned char *mem = NULL;
uint32_t size;
RsGxsGroupId id ;
serialized_groups.clear() ;
if(!RsGenExchange::getSerializedGroupData(token,id, mem,size))
{
std::cerr << "(EE) call to RsGenExchage::getSerializedGroupData() failed." << std::endl;
return false;
}
std::string radix ;
Radix64::encode(mem,size,radix) ;
serialized_groups[RsGxsId(id)] = radix ;
return true;
}
/********************************************************************************/ /********************************************************************************/
/********************************************************************************/ /********************************************************************************/
@ -4309,6 +4410,9 @@ void p3IdService::handleResponse(uint32_t token, uint32_t req_type)
case GXSIDREQ_OPINION: case GXSIDREQ_OPINION:
opinion_handlerequest(token); opinion_handlerequest(token);
break; break;
case GXSIDREQ_SERIALIZE_TO_MEMORY:
handle_get_serialized_grp(token) ;
default: default:
/* error */ /* error */
std::cerr << "p3IdService::handleResponse() Unknown Request Type: " << req_type; std::cerr << "p3IdService::handleResponse() Unknown Request Type: " << req_type;

View file

@ -212,6 +212,13 @@ private:
void init(const RsGxsIdGroupItem *item, const RsTlvPublicRSAKey& in_pub_key, const RsTlvPrivateRSAKey& in_priv_key,const std::list<RsRecognTag> &tagList); void init(const RsGxsIdGroupItem *item, const RsTlvPublicRSAKey& in_pub_key, const RsTlvPrivateRSAKey& in_priv_key,const std::list<RsRecognTag> &tagList);
}; };
struct SerialisedIdentityStruct
{
unsigned char *mMem ;
uint32_t mSize ;
time_t mLastUsageTS;
};
// Not sure exactly what should be inherited here? // Not sure exactly what should be inherited here?
// Chris - please correct as necessary. // Chris - please correct as necessary.
@ -238,6 +245,8 @@ public:
// These are exposed via RsIdentity. // These are exposed via RsIdentity.
virtual bool getGroupData(const uint32_t &token, std::vector<RsGxsIdGroup> &groups); virtual bool getGroupData(const uint32_t &token, std::vector<RsGxsIdGroup> &groups);
virtual bool getGroupSerializedData(const uint32_t &token, std::map<RsGxsId,std::string>& serialized_groups);
//virtual bool getMsgData(const uint32_t &token, std::vector<RsGxsIdOpinion> &opinions); //virtual bool getMsgData(const uint32_t &token, std::vector<RsGxsIdOpinion> &opinions);
// These are local - and not exposed via RsIdentity. // These are local - and not exposed via RsIdentity.
@ -341,6 +350,8 @@ public:
const RsIdentityUsage &use_info ); const RsIdentityUsage &use_info );
virtual bool requestPrivateKey(const RsGxsId &id); virtual bool requestPrivateKey(const RsGxsId &id);
virtual bool serialiseIdentityToMemory(const RsGxsId& id,std::string& radix_string);
virtual bool deserialiseIdentityFromMemory(const std::string& radix_string);
/**************** RsGixsReputation Implementation ****************/ /**************** RsGixsReputation Implementation ****************/
@ -433,6 +444,12 @@ private:
bool mBgSchedule_Active; bool mBgSchedule_Active;
uint32_t mBgSchedule_Mode; uint32_t mBgSchedule_Mode;
/***********************************8
* Fonction to receive and handle group serialisation to memory
*/
virtual void handle_get_serialized_grp(uint32_t token);
/************************************************************************ /************************************************************************
* pgphash processing. * pgphash processing.
* *
@ -563,6 +580,8 @@ private:
std::map<RsGxsId, std::list<RsPeerId> > mIdsNotPresent; std::map<RsGxsId, std::list<RsPeerId> > mIdsNotPresent;
std::map<RsGxsId,keyTSInfo> mKeysTS ; std::map<RsGxsId,keyTSInfo> mKeysTS ;
std::map<RsGxsId,SerialisedIdentityStruct> mSerialisedIdentities ;
// keep a list of regular contacts. This is useful to sort IDs, and allow some services to priviledged ids only. // keep a list of regular contacts. This is useful to sort IDs, and allow some services to priviledged ids only.
std::set<RsGxsId> mContacts; std::set<RsGxsId> mContacts;
RsNetworkExchangeService* mNes; RsNetworkExchangeService* mNes;

View file

@ -93,9 +93,9 @@ again:
idx = (idx + 1) % 4; idx = (idx + 1) % 4;
} }
idx = idx; //idx = idx;
return buf; return buf ;
} }
/**************** /****************
@ -147,7 +147,7 @@ again:
private: private:
static inline char *bintoasc() { static char bta[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; return bta ; } static inline char *bintoasc() { static char bta[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; return bta ; }
static inline char *asctobin() { static char s[256]; return s ; } /* runtime radix64_initd */ static inline uint8_t *asctobin() { static uint8_t s[256]; return s ; } /* runtime radix64_initd */
static int& is_radix64_initd() { static int is_inited = false ; return is_inited ; } static int& is_radix64_initd() { static int is_inited = false ; return is_inited ; }
/* hey, guess what: this is a read-only table. /* hey, guess what: this is a read-only table.

View file

@ -2394,7 +2394,7 @@ static int parse_secret_key(ops_region_t *region,ops_parse_info_t *pinfo)
else if(C.secret_key.s2k_usage != OPS_S2KU_NONE) else if(C.secret_key.s2k_usage != OPS_S2KU_NONE)
{ {
// this is V3 style, looks just like a V4 simple hash // this is V3 style, looks just like a V4 simple hash
C.secret_key.algorithm=C.secret_key.s2k_usage; C.secret_key.algorithm=(ops_symmetric_algorithm_t)C.secret_key.s2k_usage;
C.secret_key.s2k_usage=OPS_S2KU_ENCRYPTED; C.secret_key.s2k_usage=OPS_S2KU_ENCRYPTED;
C.secret_key.s2k_specifier=OPS_S2KS_SIMPLE; C.secret_key.s2k_specifier=OPS_S2KS_SIMPLE;
C.secret_key.hash_algorithm=OPS_HASH_MD5; C.secret_key.hash_algorithm=OPS_HASH_MD5;

View file

@ -651,7 +651,7 @@ static time_t parseRFC822Date(const std::string &pubDate)
offset = abs(offset); offset = abs(offset);
offset = ((offset / 100)*60 + (offset % 100))*sgn; offset = ((offset / 100)*60 + (offset % 100))*sgn;
} else { } else {
for (int i=0; known_zones[i].tzName != 0; i++) { for (int i=0; known_zones[i].tzName[0] != 0; i++) {
if (0 == strncasecmp(dateString, known_zones[i].tzName, strlen(known_zones[i].tzName))) { if (0 == strncasecmp(dateString, known_zones[i].tzName, strlen(known_zones[i].tzName))) {
offset = known_zones[i].tzOffset; offset = known_zones[i].tzOffset;
break; break;

View file

@ -66,7 +66,9 @@ private:
AVPacket decoding_buffer; AVPacket decoding_buffer;
uint64_t encoding_frame_count ; uint64_t encoding_frame_count ;
#ifdef DEBUG_MPEG_VIDEO
FILE *encoding_debug_file ; FILE *encoding_debug_file ;
#endif
}; };
// This class decodes video from a stream. It keeps a queue of // This class decodes video from a stream. It keeps a queue of

View file

@ -6,13 +6,11 @@ QT += core network
QT -= gui QT -= gui
CONFIG += c++11 CONFIG += c++11
CONFIG += dll android-g++:CONFIG += dll
android-g++:TEMPLATE = lib android-g++:TEMPLATE = lib
!android-g++:TEMPLATE = app !android-g++:TEMPLATE = app
SOURCES += service.cpp
DEPENDPATH *= ../../libresapi/src DEPENDPATH *= ../../libresapi/src
INCLUDEPATH *= ../../libresapi/src INCLUDEPATH *= ../../libresapi/src
PRE_TARGETDEPS *= ../../libresapi/src/lib/libresapi.a PRE_TARGETDEPS *= ../../libresapi/src/lib/libresapi.a
@ -22,3 +20,34 @@ DEPENDPATH *= ../../libretroshare/src
INCLUDEPATH *= ../../libretroshare/src INCLUDEPATH *= ../../libretroshare/src
PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a
LIBS *= ../../libretroshare/src/lib/libretroshare.a LIBS *= ../../libretroshare/src/lib/libretroshare.a
win32 {
OBJECTS_DIR = temp/obj
LIBS_DIR = $$PWD/../../libs/lib
LIBS += $$OUT_PWD/../../libretroshare/src/lib/libretroshare.a
LIBS += $$OUT_PWD/../../openpgpsdk/src/lib/libops.a
for(lib, LIB_DIR):LIBS += -L"$$lib"
for(bin, BIN_DIR):LIBS += -L"$$bin"
LIBS += -lssl -lcrypto -lpthread -lminiupnpc -lz -lws2_32
LIBS += -luuid -lole32 -liphlpapi -lcrypt32 -lgdi32
LIBS += -lwinmm
DEFINES *= WINDOWS_SYS WIN32_LEAN_AND_MEAN _USE_32BIT_TIME_T
DEPENDPATH += . $$INC_DIR
INCLUDEPATH += . $$INC_DIR
greaterThan(QT_MAJOR_VERSION, 4) {
# Qt 5
RC_INCLUDEPATH += $$_PRO_FILE_PWD_/../../libretroshare/src
} else {
# Qt 4
QMAKE_RC += --include-dir=$$_PRO_FILE_PWD_/../../libretroshare/src
}
}
SOURCES += service.cpp

View file

@ -24,12 +24,10 @@
# include "util/androiddebug.h" # include "util/androiddebug.h"
#endif #endif
#include "retroshare/rsinit.h"
#include "api/ApiServer.h" #include "api/ApiServer.h"
#include "api/ApiServerLocal.h" #include "api/ApiServerLocal.h"
#include "api/RsControlModule.h" #include "api/RsControlModule.h"
using namespace resource_api; using namespace resource_api;
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@ -46,7 +44,12 @@ int main(int argc, char *argv[])
dynamic_cast<resource_api::ResourceRouter*>(&ctrl_mod), dynamic_cast<resource_api::ResourceRouter*>(&ctrl_mod),
&resource_api::RsControlModule::handleRequest); &resource_api::RsControlModule::handleRequest);
QString sockPath = QString::fromStdString(RsAccounts::ConfigDirectory()); #ifdef QT_DEBUG
QString sockPath = "RS/";
#else
QString sockPath = QCoreApplication::applicationDirPath();
#endif
sockPath.append("/libresapi.sock"); sockPath.append("/libresapi.sock");
qDebug() << "Listening on:" << sockPath; qDebug() << "Listening on:" << sockPath;
ApiServerLocal apiServerLocal(&api, sockPath); (void) apiServerLocal; ApiServerLocal apiServerLocal(&api, sockPath); (void) apiServerLocal;

View file

@ -378,8 +378,12 @@ static void updateItem(QTreeWidget *treeWidget, QTreeWidgetItem *item, ChatLobby
+QObject::tr("Id:")+" "+QString::number(id,16) ; +QObject::tr("Id:")+" "+QString::number(id,16) ;
if(lobby_flags & RS_CHAT_LOBBY_FLAGS_PGP_SIGNED) if(lobby_flags & RS_CHAT_LOBBY_FLAGS_PGP_SIGNED)
{
tooltipstr += QObject::tr("\nSecurity: no anonymous IDs") ; tooltipstr += QObject::tr("\nSecurity: no anonymous IDs") ;
QColor foreground = QColor(0, 128, 0); // green
for (int column = 0; column < COLUMN_COUNT; ++column)
item->setTextColor(column, foreground);
}
item->setToolTip(0,tooltipstr) ; item->setToolTip(0,tooltipstr) ;
} }
@ -653,7 +657,9 @@ void ChatLobbyWidget::updateDisplay()
updateItem(ui.lobbyTreeWidget, item, lobby.lobby_id, lobby.lobby_name,lobby.lobby_topic, lobby.gxs_ids.size(), true, autoSubscribe,lobby_flags); updateItem(ui.lobbyTreeWidget, item, lobby.lobby_id, lobby.lobby_name,lobby.lobby_topic, lobby.gxs_ids.size(), true, autoSubscribe,lobby_flags);
} }
publicSubLobbyItem->setHidden(publicSubLobbyItem->childCount()==0); publicSubLobbyItem->setHidden(publicSubLobbyItem->childCount()==0);
publicSubLobbyItem->setText(COLUMN_NAME, tr("Public Subscribed chat rooms")+ QString(" (") + QString::number(publicSubLobbyItem->childCount())+QString(")"));
privateSubLobbyItem->setHidden(privateSubLobbyItem->childCount()==0); privateSubLobbyItem->setHidden(privateSubLobbyItem->childCount()==0);
publicLobbyItem->setText(COLUMN_NAME, tr("Public chat rooms")+ " (" + QString::number(publicLobbyItem->childCount())+QString(")"));
} }
void ChatLobbyWidget::createChatLobby() void ChatLobbyWidget::createChatLobby()

View file

@ -407,6 +407,13 @@ void SearchDialog::download()
for(std::list<RsPeerId>::const_iterator it(srcIds.begin()); it!=srcIds.end(); ++it) { for(std::list<RsPeerId>::const_iterator it(srcIds.begin()); it!=srcIds.end(); ++it) {
std::cout << *it << "-" << std::endl; std::cout << *it << "-" << std::endl;
}//for(std::list<RsPeerId>::const_iterator }//for(std::list<RsPeerId>::const_iterator
//QColor foreground = QColor(0, 128, 0); // green
QColor foreground = textColorDownloading();
QBrush brush(foreground);
for (int i = 0; i < item->columnCount(); ++i)
{
item->setForeground(i, brush);
}
}//if(!rsFiles -> FileRequest( }//if(!rsFiles -> FileRequest(
}//if (item->text(SR_HASH_COL).isEmpty()) }//if (item->text(SR_HASH_COL).isEmpty())
}//for (int i = 0 }//for (int i = 0
@ -1189,6 +1196,11 @@ void SearchDialog::insertFile(qulonglong searchId, const FileDetail& file, int s
found = true ; found = true ;
if (!item->data(SR_DATA_COL, SR_ROLE_LOCAL).toBool()) { if (!item->data(SR_DATA_COL, SR_ROLE_LOCAL).toBool()) {
FileInfo fi;
if (rsFiles->FileDetails(file.hash, RS_FILE_HINTS_DOWNLOAD, fi))
break;
QColor foreground; QColor foreground;
int sources = friendSource + anonymousSource ; int sources = friendSource + anonymousSource ;
@ -1281,6 +1293,12 @@ void SearchDialog::insertFile(qulonglong searchId, const FileDetail& file, int s
setForeground = true; setForeground = true;
} }
} }
if (rsFiles->FileDetails(file.hash, RS_FILE_HINTS_DOWNLOAD, fi))
{
//foreground = QColor(0, 128, 0); // green
foreground = textColorDownloading();
setForeground = true;
}
if (setForeground) { if (setForeground) {
QBrush brush(foreground); QBrush brush(foreground);

View file

@ -38,6 +38,7 @@ class SearchDialog : public MainPage
Q_OBJECT Q_OBJECT
Q_PROPERTY(QColor textColorLocal READ textColorLocal WRITE setTextColorLocal) Q_PROPERTY(QColor textColorLocal READ textColorLocal WRITE setTextColorLocal)
Q_PROPERTY(QColor textColorDownloading READ textColorDownloading WRITE setTextColorDownloading)
Q_PROPERTY(QColor textColorNoSources READ textColorNoSources WRITE setTextColorNoSources) Q_PROPERTY(QColor textColorNoSources READ textColorNoSources WRITE setTextColorNoSources)
Q_PROPERTY(QColor textColorLowSources READ textColorLowSources WRITE setTextColorLowSources) Q_PROPERTY(QColor textColorLowSources READ textColorLowSources WRITE setTextColorLowSources)
Q_PROPERTY(QColor textColorHighSources READ textColorHighSources WRITE setTextColorHighSources) Q_PROPERTY(QColor textColorHighSources READ textColorHighSources WRITE setTextColorHighSources)
@ -51,11 +52,13 @@ public:
void searchKeywords(const QString& keywords); void searchKeywords(const QString& keywords);
QColor textColorLocal() const { return mTextColorLocal; } QColor textColorLocal() const { return mTextColorLocal; }
QColor textColorDownloading() const { return mTextColorDownloading; }
QColor textColorNoSources() const { return mTextColorNoSources; } QColor textColorNoSources() const { return mTextColorNoSources; }
QColor textColorLowSources() const { return mTextColorLowSources; } QColor textColorLowSources() const { return mTextColorLowSources; }
QColor textColorHighSources() const { return mTextColorHighSources; } QColor textColorHighSources() const { return mTextColorHighSources; }
void setTextColorLocal(QColor color) { mTextColorLocal = color; } void setTextColorLocal(QColor color) { mTextColorLocal = color; }
void setTextColorDownloading(QColor color) { mTextColorDownloading = color; }
void setTextColorNoSources(QColor color) { mTextColorNoSources = color; } void setTextColorNoSources(QColor color) { mTextColorNoSources = color; }
void setTextColorLowSources(QColor color) { mTextColorLowSources = color; } void setTextColorLowSources(QColor color) { mTextColorLowSources = color; }
void setTextColorHighSources(QColor color) { mTextColorHighSources = color; } void setTextColorHighSources(QColor color) { mTextColorHighSources = color; }
@ -154,6 +157,7 @@ private:
/* Color definitions (for standard see qss.default) */ /* Color definitions (for standard see qss.default) */
QColor mTextColorLocal; QColor mTextColorLocal;
QColor mTextColorDownloading;
QColor mTextColorNoSources; QColor mTextColorNoSources;
QColor mTextColorLowSources; QColor mTextColorLowSources;
QColor mTextColorHighSources; QColor mTextColorHighSources;

View file

@ -55,10 +55,11 @@
*****/ *****/
// Data Requests. // Data Requests.
#define IDDIALOG_IDLIST 1 #define IDDIALOG_IDLIST 1
#define IDDIALOG_IDDETAILS 2 #define IDDIALOG_IDDETAILS 2
#define IDDIALOG_REPLIST 3 #define IDDIALOG_REPLIST 3
#define IDDIALOG_REFRESH 4 #define IDDIALOG_REFRESH 4
#define IDDIALOG_SERIALIZED_GROUP 5
#define CIRCLEGROUP_CIRCLE_COL_GROUPNAME 0 #define CIRCLEGROUP_CIRCLE_COL_GROUPNAME 0
#define CIRCLEGROUP_CIRCLE_COL_GROUPID 1 #define CIRCLEGROUP_CIRCLE_COL_GROUPID 1
@ -814,7 +815,7 @@ void IdDialog::loadCircleGroupData(const uint32_t& token)
#ifdef ID_DEBUG #ifdef ID_DEBUG
std::cerr << "Loading circle info" << std::endl; std::cerr << "Loading circle info" << std::endl;
#endif #endif
std::vector<RsGxsCircleGroup> circle_grp_v ; std::vector<RsGxsCircleGroup> circle_grp_v ;
rsGxsCircles->getGroupData(token, circle_grp_v); rsGxsCircles->getGroupData(token, circle_grp_v);
@ -1207,6 +1208,7 @@ void IdDialog::CircleListCustomPopupMenu( QPoint )
contextMnu.exec(QCursor::pos()); contextMnu.exec(QCursor::pos());
} }
#ifdef SUSPENDED
static void set_item_background(QTreeWidgetItem *item, uint32_t type) static void set_item_background(QTreeWidgetItem *item, uint32_t type)
{ {
QBrush brush; QBrush brush;
@ -1247,7 +1249,6 @@ static void update_children_background(QTreeWidgetItem *item, uint32_t type)
} }
} }
#ifdef SUSPENDED
static void set_tree_background(QTreeWidget *tree, uint32_t type) static void set_tree_background(QTreeWidget *tree, uint32_t type)
{ {
std::cerr << "CirclesDialog set_tree_background()"; std::cerr << "CirclesDialog set_tree_background()";
@ -1385,6 +1386,8 @@ void IdDialog::updateSelection()
} }
} }
void IdDialog::requestIdList() void IdDialog::requestIdList()
{ {
//Disable by default, will be enable by insertIdDetails() //Disable by default, will be enable by insertIdDetails()
@ -1990,7 +1993,7 @@ QString IdDialog::createUsageString(const RsIdentityUsage& u) const
return tr("Membership verification in circle %1.").arg(QString::fromStdString(u.mGrpId.toStdString())); return tr("Membership verification in circle %1.").arg(QString::fromStdString(u.mGrpId.toStdString()));
} }
#warning TODO! Add the different strings and translations here. #warning TODO! csoler 2017-01-03: Add the different strings and translations here.
default: default:
return QString("Undone yet"); return QString("Undone yet");
} }
@ -2174,6 +2177,45 @@ void IdDialog::insertRepList(uint32_t token)
mStateHelper->setActive(IDDIALOG_REPLIST, true); mStateHelper->setActive(IDDIALOG_REPLIST, true);
} }
void IdDialog::handleSerializedGroupData(uint32_t token)
{
std::map<RsGxsId,std::string> serialized_group_map ;
rsIdentity->getGroupSerializedData(token, serialized_group_map);
if(serialized_group_map.size() < 1)
{
std::cerr << "(EE) Cannot get radix data " << std::endl;
return;
}
if(serialized_group_map.size() > 1)
{
std::cerr << "(EE) Too many results for serialized data" << std::endl;
return;
}
RsGxsId gxs_id = serialized_group_map.begin()->first ;
std::string radix = serialized_group_map.begin()->second ;
RsIdentityDetails details ;
if(!rsIdentity->getIdDetails(gxs_id,details))
{
std::cerr << "(EE) Cannot get id details for key " << gxs_id << std::endl;
return;
}
QList<RetroShareLink> urls ;
RetroShareLink link ;
link.createIdentity(gxs_id,QString::fromUtf8(details.mNickname.c_str()),QString::fromStdString(radix)) ;
urls.push_back(link);
RSLinkClipboard::copyLinks(urls) ;
QMessageBox::information(NULL,tr("information"),tr("This identity link was copied to your clipboard. Paste it in a mail, or a message to transmit the identity to someone.")) ;
}
void IdDialog::loadRequest(const TokenQueue * queue, const TokenRequest &req) void IdDialog::loadRequest(const TokenQueue * queue, const TokenRequest &req)
{ {
#ifdef ID_DEBUG #ifdef ID_DEBUG
@ -2197,6 +2239,10 @@ void IdDialog::loadRequest(const TokenQueue * queue, const TokenRequest &req)
insertRepList(req.mToken); insertRepList(req.mToken);
break; break;
case IDDIALOG_SERIALIZED_GROUP:
handleSerializedGroupData(req.mToken);
break;
case IDDIALOG_REFRESH: case IDDIALOG_REFRESH:
// replaced by RsGxsUpdateBroadcastPage // replaced by RsGxsUpdateBroadcastPage
// updateDisplay(true); // updateDisplay(true);
@ -2240,165 +2286,211 @@ void IdDialog::loadRequest(const TokenQueue * queue, const TokenRequest &req)
void IdDialog::IdListCustomPopupMenu( QPoint ) void IdDialog::IdListCustomPopupMenu( QPoint )
{ {
QMenu *contextMenu = new QMenu(this); QMenu *contextMenu = new QMenu(this);
std::list<RsGxsId> own_identities ; std::list<RsGxsId> own_identities ;
rsIdentity->getOwnIds(own_identities) ; rsIdentity->getOwnIds(own_identities) ;
// make some stats about what's selected. If the same value is used for all selected items, it can be switched. // make some stats about what's selected. If the same value is used for all selected items, it can be switched.
QList<QTreeWidgetItem *> selected_items = ui->idTreeWidget->selectedItems(); QList<QTreeWidgetItem *> selected_items = ui->idTreeWidget->selectedItems();
bool root_node_present = false ; bool root_node_present = false ;
bool one_item_owned_by_you = false ; bool one_item_owned_by_you = false ;
uint32_t n_positive_reputations = 0 ; uint32_t n_positive_reputations = 0 ;
uint32_t n_negative_reputations = 0 ; uint32_t n_negative_reputations = 0 ;
uint32_t n_neutral_reputations = 0 ; uint32_t n_neutral_reputations = 0 ;
uint32_t n_is_a_contact = 0 ; uint32_t n_is_a_contact = 0 ;
uint32_t n_is_not_a_contact = 0 ; uint32_t n_is_not_a_contact = 0 ;
uint32_t n_selected_items =0 ; uint32_t n_selected_items =0 ;
for(QList<QTreeWidgetItem*>::const_iterator it(selected_items.begin());it!=selected_items.end();++it) for(QList<QTreeWidgetItem*>::const_iterator it(selected_items.begin());it!=selected_items.end();++it)
{ {
if(*it == allItem || *it == contactsItem || *it == ownItem) if(*it == allItem || *it == contactsItem || *it == ownItem)
{
root_node_present = true ;
continue ;
}
uint32_t item_flags = (*it)->data(RSID_COL_KEYID,Qt::UserRole).toUInt() ;
if(item_flags & RSID_FILTER_OWNED_BY_YOU)
one_item_owned_by_you = true ;
#ifdef ID_DEBUG
std::cerr << " item flags = " << item_flags << std::endl;
#endif
RsGxsId keyId((*it)->text(RSID_COL_KEYID).toStdString());
RsIdentityDetails det ;
rsIdentity->getIdDetails(keyId,det) ;
switch(det.mReputation.mOwnOpinion)
{
case RsReputations::OPINION_NEGATIVE: ++n_negative_reputations ;
break ;
case RsReputations::OPINION_POSITIVE: ++n_positive_reputations ;
break ;
case RsReputations::OPINION_NEUTRAL: ++n_neutral_reputations ;
break ;
}
++n_selected_items ;
if(rsIdentity->isARegularContact(keyId))
++n_is_a_contact ;
else
++n_is_not_a_contact ;
}
if(!root_node_present) // don't show menu if some of the root nodes are present
{ {
root_node_present = true ;
if(!one_item_owned_by_you) continue ;
{
QWidget *widget = new QWidget(contextMenu);
widget->setStyleSheet( ".QWidget{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #FEFEFE, stop:1 #E8E8E8); border: 1px solid #CCCCCC;}");
// create menu header
QHBoxLayout *hbox = new QHBoxLayout(widget);
hbox->setMargin(0);
hbox->setSpacing(6);
QLabel *iconLabel = new QLabel(widget);
QPixmap pix = QPixmap(":/images/user/friends24.png").scaledToHeight(QFontMetricsF(iconLabel->font()).height()*1.5);
iconLabel->setPixmap(pix);
iconLabel->setMaximumSize(iconLabel->frameSize().height() + pix.height(), pix.width());
hbox->addWidget(iconLabel);
QLabel *textLabel = new QLabel("<strong>" + ui->titleBarLabel->text() + "</strong>", widget);
hbox->addWidget(textLabel);
QSpacerItem *spacerItem = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
hbox->addItem(spacerItem);
widget->setLayout(hbox);
QWidgetAction *widgetAction = new QWidgetAction(this);
widgetAction->setDefaultWidget(widget);
contextMenu->addAction(widgetAction);
if(n_selected_items == 1) // if only one item is selected, allow to chat with this item
{
if(own_identities.size() <= 1)
{
QAction *action = contextMenu->addAction(QIcon(":/images/chat_24.png"), tr("Chat with this person"), this, SLOT(chatIdentity()));
if(own_identities.empty())
action->setEnabled(false) ;
else
action->setData(QString::fromStdString((own_identities.front()).toStdString())) ;
}
else
{
QMenu *mnu = contextMenu->addMenu(QIcon(":/images/chat_24.png"),tr("Chat with this person as...")) ;
for(std::list<RsGxsId>::const_iterator it=own_identities.begin();it!=own_identities.end();++it)
{
RsIdentityDetails idd ;
rsIdentity->getIdDetails(*it,idd) ;
QPixmap pixmap ;
if(idd.mAvatar.mSize == 0 || !pixmap.loadFromData(idd.mAvatar.mData, idd.mAvatar.mSize, "PNG"))
pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(*it)) ;
QAction *action = mnu->addAction(QIcon(pixmap), QString("%1 (%2)").arg(QString::fromUtf8(idd.mNickname.c_str()), QString::fromStdString((*it).toStdString())), this, SLOT(chatIdentity()));
action->setData(QString::fromStdString((*it).toStdString())) ;
}
}
}
// always allow to send messages
contextMenu->addAction(QIcon(":/images/mail_new.png"), tr("Send message"), this, SLOT(sendMsg()));
contextMenu->addSeparator();
if(n_is_a_contact == 0)
contextMenu->addAction(QIcon(), tr("Add to Contacts"), this, SLOT(addtoContacts()));
if(n_is_not_a_contact == 0)
contextMenu->addAction(QIcon(":/images/cancel.png"), tr("Remove from Contacts"), this, SLOT(removefromContacts()));
contextMenu->addSeparator();
if(n_positive_reputations == 0) // only unban when all items are banned
contextMenu->addAction(QIcon(":/icons/png/thumbs-up.png"), tr("Set positive opinion"), this, SLOT(positivePerson()));
if(n_neutral_reputations == 0) // only unban when all items are banned
contextMenu->addAction(QIcon(":/icons/png/thumbs-neutral.png"), tr("Set neutral opinion"), this, SLOT(neutralPerson()));
if(n_negative_reputations == 0)
contextMenu->addAction(QIcon(":/icons/png/thumbs-down.png"), tr("Set negative opinion"), this, SLOT(negativePerson()));
}
if(one_item_owned_by_you && n_selected_items==1)
{
contextMenu->addSeparator();
contextMenu->addAction(ui->editIdentity);
contextMenu->addAction(ui->removeIdentity);
}
} }
contextMenu = ui->idTreeWidget->createStandardContextMenu(contextMenu); uint32_t item_flags = (*it)->data(RSID_COL_KEYID,Qt::UserRole).toUInt() ;
contextMenu->exec(QCursor::pos()); if(item_flags & RSID_FILTER_OWNED_BY_YOU)
delete contextMenu; one_item_owned_by_you = true ;
#ifdef ID_DEBUG
std::cerr << " item flags = " << item_flags << std::endl;
#endif
RsGxsId keyId((*it)->text(RSID_COL_KEYID).toStdString());
RsIdentityDetails det ;
rsIdentity->getIdDetails(keyId,det) ;
switch(det.mReputation.mOwnOpinion)
{
case RsReputations::OPINION_NEGATIVE: ++n_negative_reputations ;
break ;
case RsReputations::OPINION_POSITIVE: ++n_positive_reputations ;
break ;
case RsReputations::OPINION_NEUTRAL: ++n_neutral_reputations ;
break ;
}
++n_selected_items ;
if(rsIdentity->isARegularContact(keyId))
++n_is_a_contact ;
else
++n_is_not_a_contact ;
}
if(!root_node_present) // don't show menu if some of the root nodes are present
{
if(!one_item_owned_by_you)
{
QWidget *widget = new QWidget(contextMenu);
widget->setStyleSheet( ".QWidget{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #FEFEFE, stop:1 #E8E8E8); border: 1px solid #CCCCCC;}");
// create menu header
QHBoxLayout *hbox = new QHBoxLayout(widget);
hbox->setMargin(0);
hbox->setSpacing(6);
QLabel *iconLabel = new QLabel(widget);
QPixmap pix = QPixmap(":/images/user/friends24.png").scaledToHeight(QFontMetricsF(iconLabel->font()).height()*1.5);
iconLabel->setPixmap(pix);
iconLabel->setMaximumSize(iconLabel->frameSize().height() + pix.height(), pix.width());
hbox->addWidget(iconLabel);
QLabel *textLabel = new QLabel("<strong>" + ui->titleBarLabel->text() + "</strong>", widget);
hbox->addWidget(textLabel);
QSpacerItem *spacerItem = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
hbox->addItem(spacerItem);
widget->setLayout(hbox);
QWidgetAction *widgetAction = new QWidgetAction(this);
widgetAction->setDefaultWidget(widget);
contextMenu->addAction(widgetAction);
if(n_selected_items == 1) // if only one item is selected, allow to chat with this item
{
if(own_identities.size() <= 1)
{
QAction *action = contextMenu->addAction(QIcon(":/images/chat_24.png"), tr("Chat with this person"), this, SLOT(chatIdentity()));
if(own_identities.empty())
action->setEnabled(false) ;
else
action->setData(QString::fromStdString((own_identities.front()).toStdString())) ;
}
else
{
QMenu *mnu = contextMenu->addMenu(QIcon(":/images/chat_24.png"),tr("Chat with this person as...")) ;
for(std::list<RsGxsId>::const_iterator it=own_identities.begin();it!=own_identities.end();++it)
{
RsIdentityDetails idd ;
rsIdentity->getIdDetails(*it,idd) ;
QPixmap pixmap ;
if(idd.mAvatar.mSize == 0 || !pixmap.loadFromData(idd.mAvatar.mData, idd.mAvatar.mSize, "PNG"))
pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(*it)) ;
QAction *action = mnu->addAction(QIcon(pixmap), QString("%1 (%2)").arg(QString::fromUtf8(idd.mNickname.c_str()), QString::fromStdString((*it).toStdString())), this, SLOT(chatIdentity()));
action->setData(QString::fromStdString((*it).toStdString())) ;
}
}
}
if(n_selected_items==1)
QAction *action = contextMenu->addAction(QIcon(":/images/chat_24.png"),tr("Copy identity to clipboard"),this,SLOT(copyRetroshareLink())) ;
// always allow to send messages
contextMenu->addAction(QIcon(":/images/mail_new.png"), tr("Send message"), this, SLOT(sendMsg()));
contextMenu->addSeparator();
if(n_is_a_contact == 0)
contextMenu->addAction(QIcon(), tr("Add to Contacts"), this, SLOT(addtoContacts()));
if(n_is_not_a_contact == 0)
contextMenu->addAction(QIcon(":/images/cancel.png"), tr("Remove from Contacts"), this, SLOT(removefromContacts()));
contextMenu->addSeparator();
if(n_positive_reputations == 0) // only unban when all items are banned
contextMenu->addAction(QIcon(":/icons/png/thumbs-up.png"), tr("Set positive opinion"), this, SLOT(positivePerson()));
if(n_neutral_reputations == 0) // only unban when all items are banned
contextMenu->addAction(QIcon(":/icons/png/thumbs-neutral.png"), tr("Set neutral opinion"), this, SLOT(neutralPerson()));
if(n_negative_reputations == 0)
contextMenu->addAction(QIcon(":/icons/png/thumbs-down.png"), tr("Set negative opinion"), this, SLOT(negativePerson()));
}
if(one_item_owned_by_you && n_selected_items==1)
{
contextMenu->addSeparator();
contextMenu->addAction(QIcon(":/images/chat_24.png"),tr("Copy identity to clipboard"),this,SLOT(copyRetroshareLink())) ;
contextMenu->addAction(ui->editIdentity);
contextMenu->addAction(ui->removeIdentity);
}
}
contextMenu = ui->idTreeWidget->createStandardContextMenu(contextMenu);
contextMenu->exec(QCursor::pos());
delete contextMenu;
}
void IdDialog::copyRetroshareLink()
{
QTreeWidgetItem *item = ui->idTreeWidget->currentItem();
if (!item)
{
std::cerr << "IdDialog::editIdentity() Invalid item";
std::cerr << std::endl;
return;
}
RsGxsId gxs_id(item->text(RSID_COL_KEYID).toStdString());
if(gxs_id.isNull())
{
std::cerr << "Null GXS id. Something went wrong." << std::endl;
return ;
}
RsIdentityDetails details ;
if(! rsIdentity->getIdDetails(gxs_id,details))
return ;
if (!mIdQueue)
return;
mStateHelper->setLoading(IDDIALOG_SERIALIZED_GROUP, true);
mIdQueue->cancelActiveRequestTokens(IDDIALOG_SERIALIZED_GROUP);
std::list<RsGxsGroupId> ids ;
ids.push_back(RsGxsGroupId(gxs_id)) ;
RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_GROUP_SERIALIZED_DATA;
uint32_t token;
mIdQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, ids, IDDIALOG_SERIALIZED_GROUP);
} }
void IdDialog::chatIdentity() void IdDialog::chatIdentity()

View file

@ -93,6 +93,7 @@ private slots:
void editIdentity(); void editIdentity();
void chatIdentity(); void chatIdentity();
void sendMsg(); void sendMsg();
void copyRetroshareLink();
void on_closeInfoFrameButton_clicked(); void on_closeInfoFrameButton_clicked();
void updateSelection(); void updateSelection();
@ -132,6 +133,7 @@ private:
void requestRepList(); void requestRepList();
void insertRepList(uint32_t token); void insertRepList(uint32_t token);
void handleSerializedGroupData(uint32_t token);
void requestIdEdit(std::string &id); void requestIdEdit(std::string &id);
void showIdEdit(uint32_t token); void showIdEdit(uint32_t token);

View file

@ -287,7 +287,7 @@
<height>692</height> <height>692</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="scrollAreaWidgetContentsVLayout">
<item> <item>
<widget class="QFrame" name="headerFramePerson"> <widget class="QFrame" name="headerFramePerson">
<property name="frameShape"> <property name="frameShape">
@ -296,12 +296,12 @@
<property name="frameShadow"> <property name="frameShadow">
<enum>QFrame::Raised</enum> <enum>QFrame::Raised</enum>
</property> </property>
<layout class="QGridLayout" name="gridLayout_4"> <layout class="QGridLayout" name="headerFramePersonGLayout">
<property name="horizontalSpacing"> <property name="horizontalSpacing">
<number>12</number> <number>12</number>
</property> </property>
<item row="0" column="3"> <item row="0" column="3">
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="headerFramePersonVLayout">
<item> <item>
<widget class="StyledElidedLabel" name="headerTextLabel_Person"> <widget class="StyledElidedLabel" name="headerTextLabel_Person">
<property name="text"> <property name="text">
@ -397,7 +397,7 @@
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::Box</enum> <enum>QFrame::Box</enum>
</property> </property>
<layout class="QHBoxLayout" name="distantFrameHLayout"> <layout class="QHBoxLayout" name="inviteFrameHLayout">
<property name="leftMargin"> <property name="leftMargin">
<number>6</number> <number>6</number>
</property> </property>
@ -514,7 +514,7 @@ border-image: url(:/images/closepressed.png)
<property name="title"> <property name="title">
<string>Identity info</string> <string>Identity info</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_3"> <layout class="QGridLayout" name="detailsGroupBoxGLayout">
<item row="10" column="1"> <item row="10" column="1">
<widget class="QLineEdit" name="neighborNodesOpinion_TF"> <widget class="QLineEdit" name="neighborNodesOpinion_TF">
<property name="toolTip"> <property name="toolTip">
@ -526,7 +526,7 @@ border-image: url(:/images/closepressed.png)
</widget> </widget>
</item> </item>
<item row="8" column="0"> <item row="8" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label_YourOpinion">
<property name="text"> <property name="text">
<string>Your opinion:</string> <string>Your opinion:</string>
</property> </property>
@ -540,7 +540,7 @@ border-image: url(:/images/closepressed.png)
</widget> </widget>
</item> </item>
<item row="7" column="0" colspan="2"> <item row="7" column="0" colspan="2">
<widget class="Line" name="line"> <widget class="Line" name="line_IdInfo">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
@ -728,7 +728,7 @@ p, li { white-space: pre-wrap; }
<widget class="QLineEdit" name="lineEdit_LastUsed"/> <widget class="QLineEdit" name="lineEdit_LastUsed"/>
</item> </item>
<item row="1" column="2" rowspan="11"> <item row="1" column="2" rowspan="11">
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="avatarGLayout">
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="avatarLabel"> <widget class="QLabel" name="avatarLabel">
<property name="sizePolicy"> <property name="sizePolicy">
@ -774,12 +774,12 @@ p, li { white-space: pre-wrap; }
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="avatarOpinionHLayout">
<property name="spacing"> <property name="spacing">
<number>6</number> <number>6</number>
</property> </property>
<item> <item>
<widget class="QLabel" name="label_4"> <widget class="QLabel" name="label_PosIcon">
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>34</width> <width>34</width>
@ -813,14 +813,14 @@ p, li { white-space: pre-wrap; }
</widget> </widget>
</item> </item>
<item> <item>
<widget class="Line" name="line_3"> <widget class="Line" name="line_Opinion">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="label_5"> <widget class="QLabel" name="label_NegIcon">
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>34</width> <width>34</width>
@ -856,7 +856,7 @@ p, li { white-space: pre-wrap; }
</layout> </layout>
</item> </item>
<item row="3" column="0"> <item row="3" column="0">
<spacer name="avatarVSpacer_2"> <spacer name="avatarVSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
</property> </property>
@ -874,11 +874,11 @@ p, li { white-space: pre-wrap; }
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QGroupBox" name="groupBox"> <widget class="QGroupBox" name="usageStatisticsGBox">
<property name="title"> <property name="title">
<string>Usage statistics</string> <string>Usage statistics</string>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="usageStatisticsGBoxHLayout">
<item> <item>
<widget class="RSTextBrowser" name="usageStatistics_TB"/> <widget class="RSTextBrowser" name="usageStatistics_TB"/>
</item> </item>
@ -886,7 +886,7 @@ p, li { white-space: pre-wrap; }
</widget> </widget>
</item> </item>
<item> <item>
<spacer name="verticalSpacer_2"> <spacer name="scrollAreaWidgetContentsVSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
</property> </property>
@ -900,10 +900,8 @@ p, li { white-space: pre-wrap; }
</item> </item>
</layout> </layout>
<zorder>detailsGroupBox</zorder> <zorder>detailsGroupBox</zorder>
<zorder>detailsGroupBox</zorder> <zorder>usageStatisticsGBox</zorder>
<zorder>groupBox</zorder>
<zorder>headerFramePerson</zorder> <zorder>headerFramePerson</zorder>
<zorder>verticalSpacer_2</zorder>
</widget> </widget>
</widget> </widget>
</item> </item>

View file

@ -1207,7 +1207,7 @@ void MainWindow::showHelpDialog(const QString &topic)
void void
MainWindow::retranslateUi() MainWindow::retranslateUi()
{ {
retranslateUi(); //retranslateUi();
foreach (MainPage *page, ui->stackPages->pages()) { foreach (MainPage *page, ui->stackPages->pages()) {
page->retranslateUi(); page->retranslateUi();
} }

View file

@ -96,7 +96,7 @@ void CircleWidget::updateData(const RsGroupMetaData& gxs_group_info
} }
} }
QSize CircleWidget::sizeHint() QSize CircleWidget::sizeHint() const
{ {
QSize size; QSize size;
size.setHeight(ui->graphicsView->size().height() + ui->label->size().height()); size.setHeight(ui->graphicsView->size().height() + ui->label->size().height());

View file

@ -24,7 +24,7 @@ public:
, const RsGxsCircleDetails& details); , const RsGxsCircleDetails& details);
//Start QWidget Properties //Start QWidget Properties
QSize sizeHint(); QSize sizeHint() const;
//Start FlowLayoutItem Properties //Start FlowLayoutItem Properties
virtual const QPixmap getImage(); virtual const QPixmap getImage();
virtual const QPixmap getDragImage(); virtual const QPixmap getDragImage();

View file

@ -148,7 +148,7 @@ void IdentityWidget::updateData(const RsGxsIdGroup &gxs_group_info, const RsPeer
updateData(pgp_details); updateData(pgp_details);
} }
QSize IdentityWidget::sizeHint() QSize IdentityWidget::sizeHint() const
{ {
QSize size; QSize size;
size.setHeight(ui->graphicsView->size().height() + ui->labelName->size().height()); size.setHeight(ui->graphicsView->size().height() + ui->labelName->size().height());

View file

@ -26,7 +26,7 @@ public:
, const RsPeerDetails& pgp_details); , const RsPeerDetails& pgp_details);
//Start QWidget Properties //Start QWidget Properties
QSize sizeHint(); QSize sizeHint() const;
//Start FlowLayoutItem Properties //Start FlowLayoutItem Properties
virtual const QPixmap getImage(); virtual const QPixmap getImage();
virtual const QPixmap getDragImage(); virtual const QPixmap getDragImage();

View file

@ -901,7 +901,7 @@ void PeopleDialog::pf_dropEventOccursExt(QDropEvent *event)
QWidget *wid = QWidget *wid =
qobject_cast<QWidget *>(event->source());//QT5 return QObject qobject_cast<QWidget *>(event->source());//QT5 return QObject
FlowLayout *layout; FlowLayout *layout = NULL;
if (wid) layout = if (wid) layout =
qobject_cast<FlowLayout *>(wid->layout()); qobject_cast<FlowLayout *>(wid->layout());
if (layout) { if (layout) {
@ -991,7 +991,7 @@ void PeopleDialog::pf_dropEventOccursInt(QDropEvent *event)
QWidget *wid = QWidget *wid =
qobject_cast<QWidget *>(event->source());//QT5 return QObject qobject_cast<QWidget *>(event->source());//QT5 return QObject
FlowLayout *layout; FlowLayout *layout = NULL;
if (wid) layout = if (wid) layout =
qobject_cast<FlowLayout *>(wid->layout()); qobject_cast<FlowLayout *>(wid->layout());
if (layout) { if (layout) {

View file

@ -67,7 +67,8 @@
#define HOST_SEARCH "search" #define HOST_SEARCH "search"
#define HOST_CERTIFICATE "certificate" #define HOST_CERTIFICATE "certificate"
#define HOST_PUBLIC_MSG "public_msg" #define HOST_PUBLIC_MSG "public_msg"
#define HOST_REGEXP "file|extra|person|forum|channel|posted|search|message|certificate|private_chat|public_msg" #define HOST_IDENTITY "identity"
#define HOST_REGEXP "file|extra|person|forum|channel|posted|search|message|certificate|private_chat|public_msg|identity"
#define FILE_NAME "name" #define FILE_NAME "name"
#define FILE_SIZE "size" #define FILE_SIZE "size"
@ -89,6 +90,9 @@
#define POSTED_ID "id" #define POSTED_ID "id"
#define POSTED_MSGID "msgid" #define POSTED_MSGID "msgid"
#define IDENTITY_NAME "name"
#define IDENTITY_ID "gxsid"
#define IDENTITY_GROUP "groupdata"
#define MESSAGE_ID "id" #define MESSAGE_ID "id"
#define MESSAGE_SUBJECT "subject" #define MESSAGE_SUBJECT "subject"
@ -303,6 +307,21 @@ void RetroShareLink::fromUrl(const QUrl& url)
return; return;
} }
if(url.host() == HOST_IDENTITY) {
_type = TYPE_IDENTITY ;
QString name = decodedQueryItemValue(urlQuery, IDENTITY_NAME) ;
QString radix= decodedQueryItemValue(urlQuery, IDENTITY_GROUP) ;
QString gxsid= urlQuery.queryItemValue(IDENTITY_ID) ;
RsGxsId id(gxsid.toStdString()) ;
if(!id.isNull())
createIdentity(id,name,radix) ;
else
std::cerr << "(EE) identity link is not valid." << std::endl;
return ;
}
if (url.host() == HOST_MESSAGE) { if (url.host() == HOST_MESSAGE) {
_type = TYPE_MESSAGE; _type = TYPE_MESSAGE;
std::string id = urlQuery.queryItemValue(MESSAGE_ID).toStdString(); std::string id = urlQuery.queryItemValue(MESSAGE_ID).toStdString();
@ -312,7 +331,7 @@ void RetroShareLink::fromUrl(const QUrl& url)
if (url.host() == HOST_CERTIFICATE) { if (url.host() == HOST_CERTIFICATE) {
_type = TYPE_CERTIFICATE; _type = TYPE_CERTIFICATE;
_radix = urlQuery.queryItemValue(CERTIFICATE_RADIX); _radix = decodedQueryItemValue(urlQuery, CERTIFICATE_RADIX);
#ifdef DEBUG_RSLINK #ifdef DEBUG_RSLINK
std::cerr << "Got a certificate link!!" << std::endl; std::cerr << "Got a certificate link!!" << std::endl;
@ -333,6 +352,21 @@ RetroShareLink::RetroShareLink()
clear(); clear();
} }
bool RetroShareLink::createIdentity(const RsGxsId& id, const QString& name, const QString& radix_data)
{
clear();
_name = name;
_hash = QString::fromStdString(id.toStdString());
_radix_group_data = radix_data ;
_type = TYPE_IDENTITY;
check();
return valid();
}
bool RetroShareLink::createExtraFile(const QString& name, uint64_t size, const QString& hash,const QString& ssl_id) bool RetroShareLink::createExtraFile(const QString& name, uint64_t size, const QString& hash,const QString& ssl_id)
{ {
clear(); clear();
@ -534,6 +568,7 @@ void RetroShareLink::clear()
_GPGid = "" ; _GPGid = "" ;
_time_stamp = 0 ; _time_stamp = 0 ;
_encrypted_chat_info = "" ; _encrypted_chat_info = "" ;
_radix_group_data = "" ;
} }
void RetroShareLink::check() void RetroShareLink::check()
@ -565,6 +600,17 @@ void RetroShareLink::check()
if(!checkPGPId(_GPGid)) _valid = false ; if(!checkPGPId(_GPGid)) _valid = false ;
break ; break ;
case TYPE_IDENTITY:
if(_name.isNull())
_valid = false ;
if(_radix_group_data.isNull())
_valid = false ;
if(_hash.isNull())
_valid = false ;
break ;
case TYPE_PERSON: case TYPE_PERSON:
if(_size != 0) if(_size != 0)
_valid = false; _valid = false;
@ -651,6 +697,9 @@ QString RetroShareLink::title() const
return QObject::tr("%1 (%2, Extra - Source included)").arg(hash()).arg(misc::friendlyUnit(size())); return QObject::tr("%1 (%2, Extra - Source included)").arg(hash()).arg(misc::friendlyUnit(size()));
case TYPE_FILE: case TYPE_FILE:
return QString("%1 (%2)").arg(hash()).arg(misc::friendlyUnit(size())); return QString("%1 (%2)").arg(hash()).arg(misc::friendlyUnit(size()));
case TYPE_IDENTITY:
return _name ;
case TYPE_PERSON: case TYPE_PERSON:
return PeerDefs::rsidFromId(RsPgpId(hash().toStdString())); return PeerDefs::rsidFromId(RsPgpId(hash().toStdString()));
case TYPE_FORUM: case TYPE_FORUM:
@ -711,6 +760,14 @@ QString RetroShareLink::toString() const
break; break;
case TYPE_IDENTITY:
url.setScheme(RSLINK_SCHEME) ;
url.setHost(HOST_IDENTITY) ;
urlQuery.addQueryItem(IDENTITY_ID,_hash) ;
urlQuery.addQueryItem(IDENTITY_NAME,encodeItem(_name)) ;
urlQuery.addQueryItem(IDENTITY_GROUP,encodeItem(_radix_group_data)) ;
break ;
case TYPE_EXTRAFILE: case TYPE_EXTRAFILE:
url.setScheme(RSLINK_SCHEME); url.setScheme(RSLINK_SCHEME);
url.setHost(HOST_EXTRAFILE); url.setHost(HOST_EXTRAFILE);
@ -782,9 +839,9 @@ QString RetroShareLink::toString() const
case TYPE_CERTIFICATE: case TYPE_CERTIFICATE:
url.setScheme(RSLINK_SCHEME); url.setScheme(RSLINK_SCHEME);
url.setHost(HOST_CERTIFICATE) ; url.setHost(HOST_CERTIFICATE) ;
urlQuery.addQueryItem(CERTIFICATE_RADIX, _radix); urlQuery.addQueryItem(CERTIFICATE_RADIX, encodeItem(_radix));
urlQuery.addQueryItem(CERTIFICATE_NAME, _name); urlQuery.addQueryItem(CERTIFICATE_NAME, encodeItem(_name));
urlQuery.addQueryItem(CERTIFICATE_LOCATION, _location); urlQuery.addQueryItem(CERTIFICATE_LOCATION, encodeItem(_location));
break; break;
} }
@ -798,9 +855,11 @@ QString RetroShareLink::toString() const
QString RetroShareLink::niceName() const QString RetroShareLink::niceName() const
{ {
if (type() == TYPE_PERSON) { if (type() == TYPE_PERSON)
return PeerDefs::rsid(name().toUtf8().constData(), RsPgpId(hash().toStdString())); return PeerDefs::rsid(name().toUtf8().constData(), RsPgpId(hash().toStdString()));
}
if(type() == TYPE_IDENTITY)
return QObject::tr("Identity link (name=%1, ID=%2)").arg(_name).arg(_hash) ;
if(type() == TYPE_PUBLIC_MSG) { if(type() == TYPE_PUBLIC_MSG) {
RsPeerDetails detail; RsPeerDetails detail;
@ -1011,6 +1070,7 @@ static void processList(const QStringList &list, const QString &textSingular, co
case TYPE_POSTED: case TYPE_POSTED:
case TYPE_SEARCH: case TYPE_SEARCH:
case TYPE_MESSAGE: case TYPE_MESSAGE:
case TYPE_IDENTITY:
case TYPE_CERTIFICATE: case TYPE_CERTIFICATE:
case TYPE_PUBLIC_MSG: case TYPE_PUBLIC_MSG:
case TYPE_PRIVATE_CHAT: case TYPE_PRIVATE_CHAT:
@ -1156,6 +1216,15 @@ static void processList(const QStringList &list, const QString &textSingular, co
} }
break ; break ;
case TYPE_IDENTITY:
{
if(rsIdentity->deserialiseIdentityFromMemory(link.radixGroupData().toStdString()))
QMessageBox::information(NULL,QObject::tr("Identity added to People"),QObject::tr("The identity was added to people. You can now chat with it, send messages to it, etc.")) ;
else
QMessageBox::warning(NULL,QObject::tr("Identity cannot be added to People"),QObject::tr("The identity was not added to people. Some error occured. The link is probably corrupted.")) ;
}
break;
case TYPE_FILE: case TYPE_FILE:
case TYPE_EXTRAFILE: case TYPE_EXTRAFILE:
{ {

View file

@ -68,7 +68,8 @@ class RetroShareLink
TYPE_EXTRAFILE = 0x08, TYPE_EXTRAFILE = 0x08,
TYPE_PRIVATE_CHAT = 0x09, TYPE_PRIVATE_CHAT = 0x09,
TYPE_PUBLIC_MSG = 0x0a, TYPE_PUBLIC_MSG = 0x0a,
TYPE_POSTED = 0x0b TYPE_POSTED = 0x0b,
TYPE_IDENTITY = 0x0c
}; };
public: public:
@ -76,7 +77,7 @@ class RetroShareLink
RetroShareLink(const QUrl& url); RetroShareLink(const QUrl& url);
RetroShareLink(const QString& url); RetroShareLink(const QString& url);
#warning these methods should be static and return a created link #warning csoler 2017-01-04: These methods should be static and return a created link
bool createFile(const QString& name, uint64_t size, const QString& hash); bool createFile(const QString& name, uint64_t size, const QString& hash);
bool createExtraFile(const QString& name, uint64_t size, const QString& hash, const QString& ssl_id); bool createExtraFile(const QString& name, uint64_t size, const QString& hash, const QString& ssl_id);
bool createPerson(const RsPgpId &id); bool createPerson(const RsPgpId &id);
@ -85,6 +86,7 @@ class RetroShareLink
bool createSearch(const QString& keywords); bool createSearch(const QString& keywords);
bool createMessage(const RsPeerId &peerId, const QString& subject); bool createMessage(const RsPeerId &peerId, const QString& subject);
bool createMessage(const RsGxsId &peerId, const QString& subject); bool createMessage(const RsGxsId &peerId, const QString& subject);
bool createIdentity(const RsGxsId& gxs_id,const QString& name,const QString& radix_data) ;
bool createCertificate(const RsPeerId &ssl_id) ; bool createCertificate(const RsPeerId &ssl_id) ;
bool createPublicMsgInvite(time_t time_stamp,const QString& pgp_id,const QString& hash) ; bool createPublicMsgInvite(time_t time_stamp,const QString& pgp_id,const QString& hash) ;
bool createUnknwonSslCertificate(const RsPeerId &sslId, const RsPgpId &gpgId = RsPgpId()) ; bool createUnknwonSslCertificate(const RsPeerId &sslId, const RsPgpId &gpgId = RsPgpId()) ;
@ -101,12 +103,13 @@ class RetroShareLink
const QString& SSLId() const { return _SSLid ; } const QString& SSLId() const { return _SSLid ; }
const QString& GPGId() const { return _GPGid ; } const QString& GPGId() const { return _GPGid ; }
const QString& localIPAndPort() const { return _loc_ip_port ; } const QString& localIPAndPort() const { return _loc_ip_port ; }
const QString& externalIPAndPort() const { return _ext_ip_port ; } const QString& externalIPAndPort() const { return _ext_ip_port ; }
const QString& dyndns() const { return _dyndns_name ; } const QString& dyndns() const { return _dyndns_name ; }
const QString& location() const { return _location ; } const QString& location() const { return _location ; }
const QString& radix() const { return _radix ; } const QString& radix() const { return _radix ; }
time_t timeStamp() const { return _time_stamp ; } time_t timeStamp() const { return _time_stamp ; }
QString title() const; QString title() const;
QString radixGroupData() const { return _radix_group_data ;}
unsigned int subType() const { return _subType; } unsigned int subType() const { return _subType; }
void setSubType(unsigned int subType) { _subType = subType; } void setSubType(unsigned int subType) { _subType = subType; }
@ -158,12 +161,13 @@ class RetroShareLink
QString _GPGBase64String ; // GPG Cert QString _GPGBase64String ; // GPG Cert
QString _GPGBase64CheckSum ; // GPG Cert QString _GPGBase64CheckSum ; // GPG Cert
QString _location ; // location QString _location ; // location
QString _ext_ip_port ; QString _ext_ip_port ;
QString _loc_ip_port ; QString _loc_ip_port ;
QString _dyndns_name ; QString _dyndns_name ;
QString _radix ; QString _radix ;
QString _encrypted_chat_info ; // encrypted data string for the recipient of a chat invite QString _encrypted_chat_info ; // encrypted data string for the recipient of a chat invite
time_t _time_stamp ; // time stamp at which the link will expire. time_t _time_stamp ; // time stamp at which the link will expire.
QString _radix_group_data;
unsigned int _subType; // for general use as sub type for _type (RSLINK_SUBTYPE_...) unsigned int _subType; // for general use as sub type for _type (RSLINK_SUBTYPE_...)
}; };

View file

@ -63,7 +63,7 @@ void ChatDialog::closeEvent(QCloseEvent *event)
emit dialogClose(this); emit dialogClose(this);
} }
void ChatDialog::init(ChatId id, const QString &title) void ChatDialog::init(const ChatId &id, const QString &title)
{ {
mChatId = id; mChatId = id;
ChatWidget *cw = getChatWidget(); ChatWidget *cw = getChatWidget();
@ -102,14 +102,14 @@ void ChatDialog::init(ChatId id, const QString &title)
if (chatflags & RS_CHAT_OPEN) { if (chatflags & RS_CHAT_OPEN) {
if (id.isLobbyId()) { if (id.isLobbyId()) {
ChatLobbyDialog* cld = new ChatLobbyDialog(id.toLobbyId()); ChatLobbyDialog* cld = new ChatLobbyDialog(id.toLobbyId());
cld->init(); cld->init(ChatId(), "");
cd = cld; cd = cld;
} }
else if(id.isDistantChatId()) else if(id.isDistantChatId())
{ {
PopupDistantChatDialog* pdcd = new PopupDistantChatDialog(id.toDistantChatId()); PopupDistantChatDialog* pdcd = new PopupDistantChatDialog(id.toDistantChatId());
pdcd->init(id.toDistantChatId()); pdcd->init(id, "");
cd = pdcd; cd = pdcd;
} }
else else

View file

@ -84,7 +84,7 @@ protected:
virtual QString getPeerName(const ChatId &sslid) const ; // can be overloaded for chat dialogs that have specific peers virtual QString getPeerName(const ChatId &sslid) const ; // can be overloaded for chat dialogs that have specific peers
virtual QString getOwnName() const; virtual QString getOwnName() const;
virtual void init(ChatId id, const QString &title); virtual void init(const ChatId &id, const QString &title);
virtual void addChatMsg(const ChatMessage& msg) = 0; virtual void addChatMsg(const ChatMessage& msg) = 0;
ChatId mChatId; ChatId mChatId;

View file

@ -304,7 +304,7 @@ void ChatLobbyDialog::showInPeopleTab()
idDialog->navigate(nickname); idDialog->navigate(nickname);
} }
void ChatLobbyDialog::init() void ChatLobbyDialog::init(const ChatId &/*id*/, const QString &/*title*/)
{ {
ChatLobbyInfo linfo ; ChatLobbyInfo linfo ;

View file

@ -71,7 +71,7 @@ protected:
virtual ~ChatLobbyDialog(); virtual ~ChatLobbyDialog();
void processSettings(bool load); void processSettings(bool load);
virtual void init(); virtual void init(const ChatId &id, const QString &title);
virtual bool canClose(); virtual bool canClose();
virtual void addChatMsg(const ChatMessage &msg); virtual void addChatMsg(const ChatMessage &msg);

View file

@ -76,7 +76,7 @@ ChatWidget::ChatWidget(QWidget *parent) :
int iconHeight = FMM*QFontMetricsF(font()).height() ; int iconHeight = FMM*QFontMetricsF(font()).height() ;
QSize iconSize = QSize(iconHeight,iconHeight); QSize iconSize = QSize(iconHeight,iconHeight);
QSize buttonSize = QSize(iconSize + QSize(FMM,FMM)); QSize buttonSize = QSize(iconSize + QSize((int)FMM,(int)FMM));
newMessages = false; newMessages = false;
typing = false; typing = false;
@ -258,7 +258,7 @@ void ChatWidget::addChatBarWidget(QWidget *w)
{ {
int iconHeight = FMM*QFontMetricsF(font()).height() ; int iconHeight = FMM*QFontMetricsF(font()).height() ;
QSize iconSize = QSize(iconHeight,iconHeight); QSize iconSize = QSize(iconHeight,iconHeight);
QSize buttonSize = QSize(iconSize + QSize(FMM,FMM)); QSize buttonSize = QSize(iconSize + QSize((int)FMM,(int)FMM));
w->setFixedSize(buttonSize); w->setFixedSize(buttonSize);
ui->pluginButtonFrame->layout()->addWidget(w) ; ui->pluginButtonFrame->layout()->addWidget(w) ;
} }

View file

@ -46,7 +46,7 @@ protected:
/** Default destructor */ /** Default destructor */
virtual ~PopupChatDialog(); virtual ~PopupChatDialog();
virtual void init(const ChatId &chat_id, const QString &title); virtual void init(const ChatId &chat_id, const QString &title);
virtual void showDialog(uint chatflags); virtual void showDialog(uint chatflags);
virtual ChatWidget *getChatWidget(); virtual ChatWidget *getChatWidget();
virtual bool hasPeerStatus() { return true; } virtual bool hasPeerStatus() { return true; }

View file

@ -63,9 +63,12 @@ PopupDistantChatDialog::PopupDistantChatDialog(const DistantChatPeerId& tunnel_i
updateDisplay() ; updateDisplay() ;
} }
void PopupDistantChatDialog::init(const DistantChatPeerId &peer_id) void PopupDistantChatDialog::init(const ChatId &chat_id, const QString &/*title*/)
{ {
_tunnel_id = peer_id; if (!chat_id.isDistantChatId())
return;
_tunnel_id = chat_id.toDistantChatId();
DistantChatPeerInfo tinfo; DistantChatPeerInfo tinfo;
if(!rsMsgs->getDistantChatStatus(_tunnel_id,tinfo)) if(!rsMsgs->getDistantChatStatus(_tunnel_id,tinfo))
@ -74,15 +77,15 @@ void PopupDistantChatDialog::init(const DistantChatPeerId &peer_id)
RsIdentityDetails iddetails ; RsIdentityDetails iddetails ;
if(rsIdentity->getIdDetails(tinfo.to_id,iddetails)) if(rsIdentity->getIdDetails(tinfo.to_id,iddetails))
PopupChatDialog::init(ChatId(peer_id), QString::fromUtf8(iddetails.mNickname.c_str())) ; PopupChatDialog::init(chat_id, QString::fromUtf8(iddetails.mNickname.c_str())) ;
else else
PopupChatDialog::init(ChatId(peer_id), QString::fromStdString(tinfo.to_id.toStdString())) ; PopupChatDialog::init(chat_id, QString::fromStdString(tinfo.to_id.toStdString())) ;
// Do not use setOwnId, because we don't want the user to change the GXS avatar from the chat window // Do not use setOwnId, because we don't want the user to change the GXS avatar from the chat window
// it will not be transmitted. // it will not be transmitted.
ui.ownAvatarWidget->setOwnId() ; // sets the flag ui.ownAvatarWidget->setOwnId() ; // sets the flag
ui.ownAvatarWidget->setId(ChatId(peer_id)) ; // sets the actual Id ui.ownAvatarWidget->setId(chat_id) ; // sets the actual Id
} }
void PopupDistantChatDialog::updateDisplay() void PopupDistantChatDialog::updateDisplay()

View file

@ -38,7 +38,7 @@ class PopupDistantChatDialog: public PopupChatDialog
/** Default destructor */ /** Default destructor */
virtual ~PopupDistantChatDialog(); virtual ~PopupDistantChatDialog();
virtual void init(const DistantChatPeerId& peer_id); virtual void init(const ChatId& chat_id, const QString &title);
virtual void closeEvent(QCloseEvent *e) ; virtual void closeEvent(QCloseEvent *e) ;
virtual QString getPeerName(const ChatId &id) const ; virtual QString getPeerName(const ChatId &id) const ;

View file

@ -76,11 +76,20 @@ RWindow::restoreWindowState()
m_bSaveStateOnClose = true; // now we save the window state on close m_bSaveStateOnClose = true; // now we save the window state on close
#if QT_VERSION >= 0x040200 #if QT_VERSION >= 0x040200
QByteArray geometry = getSetting("Geometry", QByteArray()).toByteArray(); QByteArray geo = getSetting("Geometry", QByteArray()).toByteArray();
if (geometry.isEmpty()) if (geo.isEmpty())
{
adjustSize(); adjustSize();
QRect rect = geometry();
int h = fontMetrics().height()*40;
if (rect.height()<h)
{
rect.setHeight(h);
setGeometry(rect);
}
}
else else
restoreGeometry(geometry); restoreGeometry(geo);
#else #else
QRect screen = QDesktopWidget().availableGeometry(); QRect screen = QDesktopWidget().availableGeometry();

View file

@ -239,9 +239,9 @@ void ConfCertDialog::load()
ui.version->show(); ui.version->show();
ui.label_version->show(); ui.label_version->show();
ui.groupBox->show(); //ui.groupBox->show();
ui.groupBox_4->show(); ui.groupBox_4->show();
ui.tabWidget->show(); //ui.tabWidget->show();
//ui.rsid->hide(); //ui.rsid->hide();
//ui.label_rsid->hide(); //ui.label_rsid->hide();
ui.pgpfingerprint->show(); ui.pgpfingerprint->show();

View file

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>722</width> <width>1104</width>
<height>651</height> <height>1086</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -69,7 +69,7 @@
<item row="0" column="0"> <item row="0" column="0">
<widget class="QTabWidget" name="stabWidget"> <widget class="QTabWidget" name="stabWidget">
<property name="currentIndex"> <property name="currentIndex">
<number>1</number> <number>0</number>
</property> </property>
<widget class="QWidget" name="tab"> <widget class="QWidget" name="tab">
<attribute name="icon"> <attribute name="icon">
@ -85,7 +85,7 @@
<item> <item>
<widget class="QGroupBox" name="groupBox_4"> <widget class="QGroupBox" name="groupBox_4">
<property name="title"> <property name="title">
<string>Friend info</string> <string>Node info:</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_3"> <layout class="QGridLayout" name="gridLayout_3">
<item row="3" column="1"> <item row="3" column="1">
@ -249,6 +249,114 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Current address:</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QGridLayout" name="gridLayout_12">
<item row="1" column="3">
<widget class="QSpinBox" name="localPort">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
<property name="value">
<number>7812</number>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="dynDNS"/>
</item>
<item row="2" column="3">
<widget class="QSpinBox" name="extPort">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
<property name="value">
<number>7812</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="l_dynDNS">
<property name="text">
<string>Dynamic DNS</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="localAddress"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="l_extAddress">
<property name="text">
<string>External Address</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="extAddress"/>
</item>
<item row="2" column="2">
<widget class="QLabel" name="l_portExternal">
<property name="text">
<string>Port</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="l_portLocal">
<property name="text">
<string>Port</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="l_localAddress">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>Local Address</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>List of known addresses:</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QListWidget" name="ipAddressList">
<property name="contextMenuPolicy">
<enum>Qt::DefaultContextMenu</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::MultiSelection</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item> <item>
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
@ -264,170 +372,6 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="tab_3">
<attribute name="icon">
<iconset resource="../images.qrc">
<normaloff>:/images/kcmsystem24.png</normaloff>:/images/kcmsystem24.png</iconset>
</attribute>
<attribute name="title">
<string>Connectivity</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_15">
<item row="0" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="tab_5">
<attribute name="title">
<string>Peer Addresses</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_8">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Peer Address</string>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<item row="2" column="0" colspan="2">
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>47</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0" colspan="2">
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>47</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="l_localAddress">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>Local Address</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="localAddress"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="l_extAddress">
<property name="text">
<string>External Address</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="extAddress"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="l_dynDNS">
<property name="text">
<string>Dynamic DNS</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="dynDNS"/>
</item>
<item row="0" column="2">
<widget class="QLabel" name="l_portLocal">
<property name="text">
<string>Port</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="l_portExternal">
<property name="text">
<string>Port</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QSpinBox" name="localPort">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
<property name="value">
<number>7812</number>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QSpinBox" name="extPort">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
<property name="value">
<number>7812</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_6">
<attribute name="title">
<string>Addresses list</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_9">
<item row="0" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Addresses list</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QListWidget" name="ipAddressList">
<property name="contextMenuPolicy">
<enum>Qt::DefaultContextMenu</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::MultiSelection</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_4"> <widget class="QWidget" name="tab_4">
<attribute name="title"> <attribute name="title">
<string>Retroshare Certificate</string> <string>Retroshare Certificate</string>

View file

@ -46,7 +46,7 @@
#include <math.h> #include <math.h>
static const double Pi = 3.14159265358979323846264338327950288419717; //static const double Pi = 3.14159265358979323846264338327950288419717;
Edge::Edge(Node *sourceNode, Node *destNode) Edge::Edge(Node *sourceNode, Node *destNode)
: arrowSize(10) : arrowSize(10)

View file

@ -362,7 +362,7 @@ void GraphWidget::timerEvent(QTimerEvent *event)
bool itemsMoved = false; bool itemsMoved = false;
foreach (Node *node, _nodes) foreach (Node *node, _nodes)
if(node->advance()) if(node->progress())
itemsMoved = true; itemsMoved = true;
if (!itemsMoved) { if (!itemsMoved) {

View file

@ -215,7 +215,7 @@ void Node::calculateForces(const double *map,int width,int height,int W,int H,fl
newPos.setY(qMin(qMax(newPos.y(), sceneRect.top()) , sceneRect.bottom())); newPos.setY(qMin(qMax(newPos.y(), sceneRect.top()) , sceneRect.bottom()));
} }
bool Node::advance() bool Node::progress()
{ {
if(_type == GraphWidget::ELASTIC_NODE_TYPE_OWN) if(_type == GraphWidget::ELASTIC_NODE_TYPE_OWN)
return false; return false;

View file

@ -77,7 +77,7 @@ public:
std::string descString() const { return _desc_string ; } std::string descString() const { return _desc_string ; }
void calculateForces(const double *data,int width,int height,int W,int H,float x,float y,float speedf); void calculateForces(const double *data,int width,int height,int W,int H,float x,float y,float speedf);
bool advance(); bool progress();
QRectF boundingRect() const; QRectF boundingRect() const;
QPainterPath shape() const; QPainterPath shape() const;

View file

@ -25,6 +25,7 @@
#include <QDateTime> #include <QDateTime>
#include <QMenu> #include <QMenu>
#include "gui/common/RSElidedItemDelegate.h"
#include "gui/gxs/GxsCommentTreeWidget.h" #include "gui/gxs/GxsCommentTreeWidget.h"
#include "gui/gxs/GxsCreateCommentDialog.h" #include "gui/gxs/GxsCreateCommentDialog.h"
#include "gui/gxs/GxsIdTreeWidgetItem.h" #include "gui/gxs/GxsIdTreeWidgetItem.h"
@ -57,6 +58,10 @@ GxsCommentTreeWidget::GxsCommentTreeWidget(QWidget *parent)
// QTreeWidget* widget = this; // QTreeWidget* widget = this;
setContextMenuPolicy(Qt::CustomContextMenu); setContextMenuPolicy(Qt::CustomContextMenu);
RSElidedItemDelegate *itemDelegate = new RSElidedItemDelegate(this);
itemDelegate->setSpacing(QSize(0, 2));
setItemDelegate(itemDelegate);
setWordWrap(true);
// QFont font = QFont("ARIAL", 10); // QFont font = QFont("ARIAL", 10);
// font.setBold(true); // font.setBold(true);

View file

@ -25,6 +25,8 @@
#include "GxsCreateCommentDialog.h" #include "GxsCreateCommentDialog.h"
#include "ui_GxsCreateCommentDialog.h" #include "ui_GxsCreateCommentDialog.h"
#include "util/HandleRichText.h"
#include <QMessageBox> #include <QMessageBox>
#include <iostream> #include <iostream>
@ -45,7 +47,11 @@ void GxsCreateCommentDialog::createComment()
{ {
RsGxsComment comment; RsGxsComment comment;
comment.mComment = std::string(ui->commentTextEdit->document()->toPlainText().toUtf8()); QString text = ui->commentTextEdit->toHtml();
RsHtml::optimizeHtml(text);
std::string msg = text.toUtf8().constData();
comment.mComment = msg;
comment.mMeta.mParentId = mParentId.second; comment.mMeta.mParentId = mParentId.second;
comment.mMeta.mGroupId = mParentId.first; comment.mMeta.mGroupId = mParentId.first;
comment.mMeta.mThreadId = mThreadId; comment.mMeta.mThreadId = mThreadId;

View file

@ -841,8 +841,11 @@ void GxsGroupFrameDialog::insertGroupsData(const std::list<RsGroupMetaData> &gro
/* now we can add them in as a tree! */ /* now we can add them in as a tree! */
ui->groupTreeWidget->fillGroupItems(mYourGroups, adminList); ui->groupTreeWidget->fillGroupItems(mYourGroups, adminList);
ui->groupTreeWidget->fillGroupItems(mSubscribedGroups, subList); ui->groupTreeWidget->fillGroupItems(mSubscribedGroups, subList);
mSubscribedGroups->setText(2, QString::number(mSubscribedGroups->childCount())); // 1 COLUMN_UNREAD 2 COLUMN_POPULARITY
ui->groupTreeWidget->fillGroupItems(mPopularGroups, popList); ui->groupTreeWidget->fillGroupItems(mPopularGroups, popList);
mPopularGroups->setText(2, QString::number(mPopularGroups->childCount()));
ui->groupTreeWidget->fillGroupItems(mOtherGroups, otherList); ui->groupTreeWidget->fillGroupItems(mOtherGroups, otherList);
mOtherGroups->setText(2, QString::number(mOtherGroups->childCount()));
mInFill = false; mInFill = false;

View file

@ -45,12 +45,13 @@
#define CREATEGXSFORUMMSG_FORUMINFO 1 #define CREATEGXSFORUMMSG_FORUMINFO 1
#define CREATEGXSFORUMMSG_PARENTMSG 2 #define CREATEGXSFORUMMSG_PARENTMSG 2
#define CREATEGXSFORUMMSG_CIRCLENFO 3 #define CREATEGXSFORUMMSG_CIRCLENFO 3
#define CREATEGXSFORUMMSG_ORIGMSG 4
//#define ENABLE_GENERATE //#define ENABLE_GENERATE
/** Constructor */ /** Constructor */
CreateGxsForumMsg::CreateGxsForumMsg(const RsGxsGroupId &fId, const RsGxsMessageId &pId) CreateGxsForumMsg::CreateGxsForumMsg(const RsGxsGroupId &fId, const RsGxsMessageId &pId,const RsGxsMessageId& mOId,const RsGxsId& posterId)
: QDialog(NULL, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint), mForumId(fId), mParentId(pId) : QDialog(NULL, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint), mForumId(fId), mParentId(pId), mOrigMsgId(mOId),mPosterId(posterId)
{ {
/* Invoke the Qt Designer generated object setup routine */ /* Invoke the Qt Designer generated object setup routine */
ui.setupUi(this); ui.setupUi(this);
@ -75,7 +76,14 @@ CreateGxsForumMsg::CreateGxsForumMsg(const RsGxsGroupId &fId, const RsGxsMessage
mStateHelper->addLoadPlaceholder(CREATEGXSFORUMMSG_PARENTMSG, ui.forumSubject); mStateHelper->addLoadPlaceholder(CREATEGXSFORUMMSG_PARENTMSG, ui.forumSubject);
mStateHelper->addClear(CREATEGXSFORUMMSG_PARENTMSG, ui.forumName); mStateHelper->addClear(CREATEGXSFORUMMSG_PARENTMSG, ui.forumName);
QString text = pId.isNull() ? tr("Start New Thread") : tr("Post Forum Message"); mStateHelper->addWidget(CREATEGXSFORUMMSG_ORIGMSG, ui.buttonBox->button(QDialogButtonBox::Ok));
mStateHelper->addWidget(CREATEGXSFORUMMSG_ORIGMSG, ui.innerFrame);
mStateHelper->addLoadPlaceholder(CREATEGXSFORUMMSG_ORIGMSG, ui.forumName);
mStateHelper->addLoadPlaceholder(CREATEGXSFORUMMSG_ORIGMSG, ui.forumSubject);
mStateHelper->addClear(CREATEGXSFORUMMSG_ORIGMSG, ui.forumName);
QString text = mOId.isNull()?(pId.isNull() ? tr("Start New Thread") : tr("Post Forum Message")):tr("Edit Message");
setWindowTitle(text); setWindowTitle(text);
ui.headerFrame->setHeaderImage(QPixmap(":/images/konversation64.png")); ui.headerFrame->setHeaderImage(QPixmap(":/images/konversation64.png"));
@ -103,7 +111,7 @@ CreateGxsForumMsg::CreateGxsForumMsg(const RsGxsGroupId &fId, const RsGxsMessage
mParentMsgLoaded = false; mParentMsgLoaded = false;
mForumMetaLoaded = false; mForumMetaLoaded = false;
mForumCircleLoaded = false; mForumCircleLoaded = false;
newMsg(); newMsg();
@ -129,13 +137,24 @@ void CreateGxsForumMsg::newMsg()
//std::cerr << "Initing ID chooser. Sign flags = " << std::hex << mForumMeta.mSignFlags << std::dec << std::endl; //std::cerr << "Initing ID chooser. Sign flags = " << std::hex << mForumMeta.mSignFlags << std::dec << std::endl;
ui.idChooser->loadIds(IDCHOOSER_ID_REQUIRED, RsGxsId()); if(!mPosterId.isNull())
{
std::set<RsGxsId> id_set ;
id_set.insert(mPosterId) ;
ui.idChooser->loadIds(IDCHOOSER_ID_REQUIRED | IDCHOOSER_NO_CREATE, mPosterId);
ui.idChooser->setIdConstraintSet(id_set);
}
else
ui.idChooser->loadIds(IDCHOOSER_ID_REQUIRED, mPosterId);
if (mForumId.isNull()) { if (mForumId.isNull()) {
mStateHelper->setActive(CREATEGXSFORUMMSG_FORUMINFO, false); mStateHelper->setActive(CREATEGXSFORUMMSG_FORUMINFO, false);
mStateHelper->setActive(CREATEGXSFORUMMSG_PARENTMSG, false); mStateHelper->setActive(CREATEGXSFORUMMSG_PARENTMSG, false);
mStateHelper->setActive(CREATEGXSFORUMMSG_ORIGMSG, false);
mStateHelper->clear(CREATEGXSFORUMMSG_FORUMINFO); mStateHelper->clear(CREATEGXSFORUMMSG_FORUMINFO);
mStateHelper->clear(CREATEGXSFORUMMSG_PARENTMSG); mStateHelper->clear(CREATEGXSFORUMMSG_PARENTMSG);
mStateHelper->clear(CREATEGXSFORUMMSG_ORIGMSG);
ui.forumName->setText(tr("No Forum")); ui.forumName->setText(tr("No Forum"));
return; return;
}//if ( mForumId.isNull()) }//if ( mForumId.isNull())
@ -174,11 +193,53 @@ void CreateGxsForumMsg::newMsg()
uint32_t token; uint32_t token;
mForumQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, CREATEGXSFORUMMSG_PARENTMSG); mForumQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, CREATEGXSFORUMMSG_PARENTMSG);
}//if (mParentId.isNull()) }//if (mParentId.isNull())
if (mOrigMsgId.isNull()) {
mStateHelper->setActive(CREATEGXSFORUMMSG_ORIGMSG, true);
mOrigMsgLoaded = true;
} else {
mStateHelper->setLoading(CREATEGXSFORUMMSG_ORIGMSG, true);
RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
GxsMsgReq msgIds;
std::vector<RsGxsMessageId> &vect = msgIds[mForumId];
vect.push_back(mOrigMsgId);
//std::cerr << "ForumsV2Dialog::newMsg() Requesting Parent Summary(" << mParentId << ")";
//std::cerr << std::endl;
uint32_t token;
mForumQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, CREATEGXSFORUMMSG_ORIGMSG);
}//if (mParentId.isNull())
} }
void CreateGxsForumMsg::loadFormInformation() void CreateGxsForumMsg::loadFormInformation()
{ {
if (!mParentId.isNull()) { if (!mOrigMsgId.isNull())
{
if (mOrigMsgLoaded) {
mStateHelper->setActive(CREATEGXSFORUMMSG_ORIGMSG, true);
mStateHelper->setLoading(CREATEGXSFORUMMSG_ORIGMSG, false);
} else {
//std::cerr << "CreateGxsForumMsg::loadMsgInformation() ParentMsg not Loaded Yet";
//std::cerr << std::endl;
mStateHelper->setActive(CREATEGXSFORUMMSG_ORIGMSG, false);
return;
}
}
else
{
mStateHelper->setActive(CREATEGXSFORUMMSG_ORIGMSG, true);
mStateHelper->setLoading(CREATEGXSFORUMMSG_ORIGMSG, false);
}
if (!mParentId.isNull())
{
if (mParentMsgLoaded) { if (mParentMsgLoaded) {
mStateHelper->setActive(CREATEGXSFORUMMSG_PARENTMSG, true); mStateHelper->setActive(CREATEGXSFORUMMSG_PARENTMSG, true);
mStateHelper->setLoading(CREATEGXSFORUMMSG_PARENTMSG, false); mStateHelper->setLoading(CREATEGXSFORUMMSG_PARENTMSG, false);
@ -190,7 +251,9 @@ void CreateGxsForumMsg::loadFormInformation()
return; return;
} }
} else { }
else
{
mStateHelper->setActive(CREATEGXSFORUMMSG_PARENTMSG, true); mStateHelper->setActive(CREATEGXSFORUMMSG_PARENTMSG, true);
mStateHelper->setLoading(CREATEGXSFORUMMSG_PARENTMSG, false); mStateHelper->setLoading(CREATEGXSFORUMMSG_PARENTMSG, false);
} }
@ -212,14 +275,24 @@ void CreateGxsForumMsg::loadFormInformation()
//std::cerr << "CreateGxsForumMsg::loadMsgInformation() using signFlags=" << std::hex << mForumMeta.mSignFlags << std::dec << std::endl; //std::cerr << "CreateGxsForumMsg::loadMsgInformation() using signFlags=" << std::hex << mForumMeta.mSignFlags << std::dec << std::endl;
if( (mForumMeta.mSignFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) || (mForumMeta.mSignFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG_KNOWN)) uint32_t fl = IDCHOOSER_ID_REQUIRED ;
ui.idChooser->setFlags(IDCHOOSER_ID_REQUIRED | IDCHOOSER_NON_ANONYMOUS) ;
else if( (mForumMeta.mSignFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) || (mForumMeta.mSignFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG_KNOWN))
ui.idChooser->setFlags(IDCHOOSER_ID_REQUIRED) ; fl |= IDCHOOSER_NON_ANONYMOUS ;
if(!mPosterId.isNull())
fl |= IDCHOOSER_NO_CREATE;
ui.idChooser->setFlags(fl) ;
QString name = QString::fromUtf8(mForumMeta.mGroupName.c_str()); QString name = QString::fromUtf8(mForumMeta.mGroupName.c_str());
QString subj; QString subj;
if (!mParentId.isNull())
if(!mOrigMsgId.isNull())
{
subj = QString::fromUtf8(mOrigMsg.mMeta.mMsgName.c_str());
}
else if (!mParentId.isNull())
{ {
QString title = QString::fromUtf8(mParentMsg.mMeta.mMsgName.c_str()); QString title = QString::fromUtf8(mParentMsg.mMeta.mMsgName.c_str());
name += " " + tr("In Reply to") + ": "; name += " " + tr("In Reply to") + ": ";
@ -228,17 +301,14 @@ void CreateGxsForumMsg::loadFormInformation()
QString text = title; QString text = title;
if (text.startsWith("Re:", Qt::CaseInsensitive)) if (text.startsWith("Re:", Qt::CaseInsensitive))
{
subj = title; subj = title;
}
else else
{
subj = "Re: " + title; subj = "Re: " + title;
}
} }
ui.forumName->setText(misc::removeNewLine(name)); ui.forumName->setText(misc::removeNewLine(name));
ui.forumSubject->setText(misc::removeNewLine(subj)); ui.forumSubject->setText(misc::removeNewLine(subj));
//ui.forumSubject->setReadOnly(!mOrigMsgId.isNull());
if (ui.forumSubject->text().isEmpty()) if (ui.forumSubject->text().isEmpty())
{ {
@ -286,6 +356,7 @@ void CreateGxsForumMsg::createMsg()
RsGxsForumMsg msg; RsGxsForumMsg msg;
msg.mMeta.mGroupId = mForumId; msg.mMeta.mGroupId = mForumId;
msg.mMeta.mParentId = mParentId; msg.mMeta.mParentId = mParentId;
msg.mMeta.mOrigMsgId = mOrigMsgId;
msg.mMeta.mMsgId.clear() ; msg.mMeta.mMsgId.clear() ;
if (mParentMsgLoaded) { if (mParentMsgLoaded) {
msg.mMeta.mThreadId = mParentMsg.mMeta.mThreadId; msg.mMeta.mThreadId = mParentMsg.mMeta.mThreadId;
@ -377,9 +448,9 @@ void CreateGxsForumMsg::reject()
{ {
if (ui.forumMessage->document()->isModified()) { if (ui.forumMessage->document()->isModified()) {
QMessageBox::StandardButton ret; QMessageBox::StandardButton ret;
ret = QMessageBox::warning(this, tr("Forum Message"), ret = QMessageBox::warning(this, tr("Cancel Forum Message"),
tr("Forum Message has not been Sent.\n" tr("Forum Message has not been sent yet!\n"
"Do you want to reject this message?"), "Do you want to discard this message?"),
QMessageBox::Yes | QMessageBox::No); QMessageBox::Yes | QMessageBox::No);
switch (ret) { switch (ret) {
case QMessageBox::Yes: case QMessageBox::Yes:
@ -521,6 +592,35 @@ void CreateGxsForumMsg::loadForumCircleInfo(const uint32_t& token)
} }
} }
void CreateGxsForumMsg::loadOrigMsg(const uint32_t &token)
{
//std::cerr << "CreateGxsForumMsg::loadParentMsg()";
//std::cerr << std::endl;
// Only grab one.... ignore more (shouldn't be any).
std::vector<RsGxsForumMsg> msgs;
if (rsGxsForums->getMsgData(token, msgs))
{
if (msgs.size() != 1)
{
/* error */
std::cerr << "CreateGxsForumMsg::loadOrigMsg() ERROR wrong number of msgs";
std::cerr << std::endl;
mStateHelper->setActive(CREATEGXSFORUMMSG_ORIGMSG, false);
mStateHelper->setLoading(CREATEGXSFORUMMSG_ORIGMSG, false);
return;
}
mOrigMsg = msgs[0];
mOrigMsgLoaded = true;
loadFormInformation();
}
}
void CreateGxsForumMsg::loadParentMsg(const uint32_t &token) void CreateGxsForumMsg::loadParentMsg(const uint32_t &token)
{ {
//std::cerr << "CreateGxsForumMsg::loadParentMsg()"; //std::cerr << "CreateGxsForumMsg::loadParentMsg()";
@ -562,6 +662,9 @@ void CreateGxsForumMsg::loadRequest(const TokenQueue *queue, const TokenRequest
case CREATEGXSFORUMMSG_FORUMINFO: case CREATEGXSFORUMMSG_FORUMINFO:
loadForumInfo(req.mToken); loadForumInfo(req.mToken);
break; break;
case CREATEGXSFORUMMSG_ORIGMSG:
loadOrigMsg(req.mToken);
break;
case CREATEGXSFORUMMSG_PARENTMSG: case CREATEGXSFORUMMSG_PARENTMSG:
loadParentMsg(req.mToken); loadParentMsg(req.mToken);
break; break;

View file

@ -36,7 +36,7 @@ class CreateGxsForumMsg : public QDialog, public TokenResponse
Q_OBJECT Q_OBJECT
public: public:
CreateGxsForumMsg(const RsGxsGroupId &fId, const RsGxsMessageId &pId); CreateGxsForumMsg(const RsGxsGroupId &fId, const RsGxsMessageId &pId, const RsGxsMessageId &moId, const RsGxsId &posterId = RsGxsId());
~CreateGxsForumMsg(); ~CreateGxsForumMsg();
void newMsg(); /* cleanup */ void newMsg(); /* cleanup */
@ -61,18 +61,24 @@ private:
void loadForumInfo(const uint32_t &token); void loadForumInfo(const uint32_t &token);
void loadParentMsg(const uint32_t &token); void loadParentMsg(const uint32_t &token);
void loadOrigMsg(const uint32_t &token);
void loadForumCircleInfo(const uint32_t &token); void loadForumCircleInfo(const uint32_t &token);
RsGxsGroupId mForumId; RsGxsGroupId mForumId;
RsGxsCircleId mCircleId ; RsGxsCircleId mCircleId ;
RsGxsMessageId mParentId; RsGxsMessageId mParentId;
RsGxsMessageId mOrigMsgId;
RsGxsId mPosterId;
bool mParentMsgLoaded; bool mParentMsgLoaded;
bool mOrigMsgLoaded;
bool mForumMetaLoaded; bool mForumMetaLoaded;
bool mForumCircleLoaded ; bool mForumCircleLoaded ;
RsGxsForumMsg mParentMsg; RsGxsForumMsg mParentMsg;
RsGxsForumMsg mOrigMsg;
RsGroupMetaData mForumMeta; RsGroupMetaData mForumMeta;
RsGxsCircleGroup mForumCircleData ; RsGxsCircleGroup mForumCircleData ;
TokenQueue *mForumQueue; TokenQueue *mForumQueue;
TokenQueue *mCirclesQueue; TokenQueue *mCirclesQueue;

View file

@ -160,6 +160,7 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget
mTokenTypeNegativeAuthor = nextTokenType(); mTokenTypeNegativeAuthor = nextTokenType();
mTokenTypeNeutralAuthor = nextTokenType(); mTokenTypeNeutralAuthor = nextTokenType();
mTokenTypePositiveAuthor = nextTokenType(); mTokenTypePositiveAuthor = nextTokenType();
mTokenTypeEditForumMessage = nextTokenType();
setUpdateWhenInvisible(true); setUpdateWhenInvisible(true);
@ -199,6 +200,7 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget
ui->threadTreeWidget->setItemDelegateForColumn(COLUMN_THREAD_DISTRIBUTION,new DistributionItemDelegate()) ; ui->threadTreeWidget->setItemDelegateForColumn(COLUMN_THREAD_DISTRIBUTION,new DistributionItemDelegate()) ;
connect(ui->versions_CB, SIGNAL(currentIndexChanged(int)), this, SLOT(changedVersion()));
connect(ui->threadTreeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(threadListCustomPopupMenu(QPoint))); connect(ui->threadTreeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(threadListCustomPopupMenu(QPoint)));
connect(ui->postText, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuTextBrowser(QPoint))); connect(ui->postText, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuTextBrowser(QPoint)));
@ -483,11 +485,14 @@ void GxsForumThreadWidget::threadListCustomPopupMenu(QPoint /*point*/)
QMenu contextMnu(this); QMenu contextMnu(this);
QAction *editAct = new QAction(QIcon(IMAGE_MESSAGEREPLY), tr("Edit"), &contextMnu);
connect(editAct, SIGNAL(triggered()), this, SLOT(editforummessage()));
QAction *replyAct = new QAction(QIcon(IMAGE_MESSAGEREPLY), tr("Reply"), &contextMnu); QAction *replyAct = new QAction(QIcon(IMAGE_MESSAGEREPLY), tr("Reply"), &contextMnu);
connect(replyAct, SIGNAL(triggered()), this, SLOT(replytoforummessage())); connect(replyAct, SIGNAL(triggered()), this, SLOT(replytoforummessage()));
QAction *replyauthorAct = new QAction(QIcon(IMAGE_MESSAGEREPLY), tr("Reply to author with private message"), &contextMnu); QAction *replyauthorAct = new QAction(QIcon(IMAGE_MESSAGEREPLY), tr("Reply to author with private message"), &contextMnu);
connect(replyauthorAct, SIGNAL(triggered()), this, SLOT(replytomessage())); connect(replyauthorAct, SIGNAL(triggered()), this, SLOT(reply_with_private_message()));
QAction *flagaspositiveAct = new QAction(QIcon(IMAGE_POSITIVE_OPINION), tr("Give positive opinion"), &contextMnu); QAction *flagaspositiveAct = new QAction(QIcon(IMAGE_POSITIVE_OPINION), tr("Give positive opinion"), &contextMnu);
flagaspositiveAct->setToolTip(tr("This will block/hide messages from this person, and notify friend nodes.")) ; flagaspositiveAct->setToolTip(tr("This will block/hide messages from this person, and notify friend nodes.")) ;
@ -572,6 +577,18 @@ void GxsForumThreadWidget::threadListCustomPopupMenu(QPoint /*point*/)
replyauthorAct->setDisabled (true); replyauthorAct->setDisabled (true);
} }
QList<QTreeWidgetItem*> selectedItems = ui->threadTreeWidget->selectedItems();
if(selectedItems.size() == 1)
{
QTreeWidgetItem *item = *selectedItems.begin();
GxsIdRSTreeWidgetItem *gxsIdItem = dynamic_cast<GxsIdRSTreeWidgetItem*>(item);
RsGxsId author_id;
if(gxsIdItem && gxsIdItem->getId(author_id) && rsIdentity->isOwnId(author_id))
contextMnu.addAction(editAct);
}
contextMnu.addAction(replyAct); contextMnu.addAction(replyAct);
contextMnu.addAction(newthreadAct); contextMnu.addAction(newthreadAct);
QAction* action = contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copyMessageLink())); QAction* action = contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copyMessageLink()));
@ -585,8 +602,6 @@ void GxsForumThreadWidget::threadListCustomPopupMenu(QPoint /*point*/)
contextMnu.addAction(expandAll); contextMnu.addAction(expandAll);
contextMnu.addAction(collapseAll); contextMnu.addAction(collapseAll);
QList<QTreeWidgetItem*> selectedItems = ui->threadTreeWidget->selectedItems();
if(selectedItems.size() == 1) if(selectedItems.size() == 1)
{ {
QTreeWidgetItem *item = *selectedItems.begin(); QTreeWidgetItem *item = *selectedItems.begin();
@ -680,6 +695,17 @@ void GxsForumThreadWidget::togglethreadview_internal()
} }
} }
void GxsForumThreadWidget::changedVersion()
{
mThreadId = RsGxsMessageId(ui->versions_CB->itemData(ui->versions_CB->currentIndex()).toString().toStdString()) ;
if (mFillThread) {
return;
}
ui->postText->resetImagesStatus(Settings->getForumLoadEmbeddedImages()) ;
insertMessage();
}
void GxsForumThreadWidget::changedThread() void GxsForumThreadWidget::changedThread()
{ {
/* just grab the ids of the current item */ /* just grab the ids of the current item */
@ -687,8 +713,10 @@ void GxsForumThreadWidget::changedThread()
if (!item || !item->isSelected()) { if (!item || !item->isSelected()) {
mThreadId.clear(); mThreadId.clear();
mOrigThreadId.clear();
} else { } else {
mThreadId = RsGxsMessageId(item->data(COLUMN_THREAD_MSGID, Qt::DisplayRole).toString().toStdString());
mThreadId = mOrigThreadId = RsGxsMessageId(item->data(COLUMN_THREAD_MSGID, Qt::DisplayRole).toString().toStdString());
} }
if (mFillThread) { if (mFillThread) {
@ -1014,10 +1042,12 @@ void GxsForumThreadWidget::fillThreadFinished()
mLastViewType = thread->mViewType; mLastViewType = thread->mViewType;
mLastForumID = groupId(); mLastForumID = groupId();
ui->threadTreeWidget->insertTopLevelItems(0, thread->mItems); ui->threadTreeWidget->insertTopLevelItems(0, thread->mItems);
mPostVersions = thread->mPostVersions;
// clear list // clear list
thread->mItems.clear(); thread->mItems.clear();
} else { } else {
mPostVersions = thread->mPostVersions;
fillThreads(thread->mItems, thread->mExpandNewMessages, thread->mItemToExpand); fillThreads(thread->mItems, thread->mExpandNewMessages, thread->mItemToExpand);
// cleanup list // cleanup list
@ -1507,6 +1537,9 @@ void GxsForumThreadWidget::insertMessage()
mStateHelper->setActive(mTokenTypeMessageData, false); mStateHelper->setActive(mTokenTypeMessageData, false);
mStateHelper->clear(mTokenTypeMessageData); mStateHelper->clear(mTokenTypeMessageData);
ui->versions_CB->hide();
ui->time_label->show();
ui->postText->clear(); ui->postText->clear();
//ui->threadTitle->clear(); //ui->threadTitle->clear();
return; return;
@ -1517,6 +1550,9 @@ void GxsForumThreadWidget::insertMessage()
mStateHelper->setActive(mTokenTypeMessageData, false); mStateHelper->setActive(mTokenTypeMessageData, false);
mStateHelper->clear(mTokenTypeMessageData); mStateHelper->clear(mTokenTypeMessageData);
ui->versions_CB->hide();
ui->time_label->show();
//ui->threadTitle->setText(tr("Forum Description")); //ui->threadTitle->setText(tr("Forum Description"));
ui->postText->setText(mForumDescription); ui->postText->setText(mForumDescription);
return; return;
@ -1535,6 +1571,8 @@ void GxsForumThreadWidget::insertMessage()
// there is something wrong // there is something wrong
mStateHelper->setWidgetEnabled(ui->previousButton, false); mStateHelper->setWidgetEnabled(ui->previousButton, false);
mStateHelper->setWidgetEnabled(ui->nextButton, false); mStateHelper->setWidgetEnabled(ui->nextButton, false);
ui->versions_CB->hide();
ui->time_label->show();
return; return;
} }
@ -1549,6 +1587,47 @@ void GxsForumThreadWidget::insertMessage()
ui->by_text_label->hide(); ui->by_text_label->hide();
ui->by_label->hide(); ui->by_label->hide();
// add/show combobox for versions, if applicable, and enable it. If no older versions of the post available, hide the combobox.
std::cerr << "Looking into existing versions for post " << mThreadId << ", thread history: " << mPostVersions.size() << std::endl;
QMap<RsGxsMessageId,QVector<QPair<time_t,RsGxsMessageId> > >::const_iterator it = mPostVersions.find(mOrigThreadId) ;
ui->versions_CB->blockSignals(true) ;
while(ui->versions_CB->count() > 0)
ui->versions_CB->removeItem(0);
if(it != mPostVersions.end())
{
std::cerr << (*it).size() << " versions found " << std::endl;
ui->versions_CB->setVisible(true) ;
ui->time_label->hide();
int current_index = 0 ;
for(int i=0;i<(*it).size();++i)
{
ui->versions_CB->insertItem(i, ((i==0)?tr("(Latest) "):tr("(Old) "))+" "+DateTime::formatLongDateTime( (*it)[i].first));
ui->versions_CB->setItemData(i,QString::fromStdString((*it)[i].second.toStdString()));
std::cerr << " added new post version " << (*it)[i].first << " " << (*it)[i].second << std::endl;
if(mThreadId == (*it)[i].second)
current_index = i ;
}
ui->versions_CB->setCurrentIndex(current_index) ;
}
else
{
ui->versions_CB->hide();
ui->time_label->show();
}
ui->versions_CB->blockSignals(false) ;
/* request Post */ /* request Post */
RsGxsGrpMsgIdPair msgId = std::make_pair(groupId(), mThreadId); RsGxsGrpMsgIdPair msgId = std::make_pair(groupId(), mThreadId);
requestMessageData(msgId); requestMessageData(msgId);
@ -1951,7 +2030,7 @@ void GxsForumThreadWidget::createmessage()
return; return;
} }
CreateGxsForumMsg *cfm = new CreateGxsForumMsg(groupId(), mThreadId); CreateGxsForumMsg *cfm = new CreateGxsForumMsg(groupId(), mThreadId,RsGxsMessageId());
cfm->show(); cfm->show();
/* window will destroy itself! */ /* window will destroy itself! */
@ -1964,7 +2043,7 @@ void GxsForumThreadWidget::createthread()
return; return;
} }
CreateGxsForumMsg *cfm = new CreateGxsForumMsg(groupId(), RsGxsMessageId()); CreateGxsForumMsg *cfm = new CreateGxsForumMsg(groupId(), RsGxsMessageId(),RsGxsMessageId());
cfm->show(); cfm->show();
/* window will destroy itself! */ /* window will destroy itself! */
@ -2018,7 +2097,7 @@ void GxsForumThreadWidget::flagperson()
mTokenQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, token_type); mTokenQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, token_type);
} }
void GxsForumThreadWidget::replytomessage() void GxsForumThreadWidget::reply_with_private_message()
{ {
if (groupId().isNull() || mThreadId.isNull()) { if (groupId().isNull() || mThreadId.isNull()) {
QMessageBox::information(this, tr("RetroShare"),tr("You cant reply to a non-existant Message")); QMessageBox::information(this, tr("RetroShare"),tr("You cant reply to a non-existant Message"));
@ -2027,9 +2106,19 @@ void GxsForumThreadWidget::replytomessage()
// Get Message ... then complete replyMessageData(). // Get Message ... then complete replyMessageData().
RsGxsGrpMsgIdPair postId = std::make_pair(groupId(), mThreadId); RsGxsGrpMsgIdPair postId = std::make_pair(groupId(), mThreadId);
requestMsgData_ReplyMessage(postId); requestMsgData_ReplyWithPrivateMessage(postId);
} }
void GxsForumThreadWidget::editforummessage()
{
if (groupId().isNull() || mThreadId.isNull()) {
QMessageBox::information(this, tr("RetroShare"),tr("You cant reply to a non-existant Message"));
return;
}
// Get Message ... then complete replyMessageData().
RsGxsGrpMsgIdPair postId = std::make_pair(groupId(), mThreadId);
requestMsgData_EditForumMessage(postId);
}
void GxsForumThreadWidget::replytoforummessage() void GxsForumThreadWidget::replytoforummessage()
{ {
if (groupId().isNull() || mThreadId.isNull()) { if (groupId().isNull() || mThreadId.isNull()) {
@ -2082,6 +2171,29 @@ void GxsForumThreadWidget::showAuthorInPeople(const RsGxsForumMsg& msg)
requestMsgData_ShowAuthorInPeople(postId); requestMsgData_ShowAuthorInPeople(postId);
} }
void GxsForumThreadWidget::editForumMessageData(const RsGxsForumMsg& msg)
{
if ((msg.mMeta.mGroupId != groupId()) || (msg.mMeta.mMsgId != mThreadId))
{
std::cerr << "GxsForumThreadWidget::replyMessageData() ERROR Message Ids have changed!";
std::cerr << std::endl;
return;
}
if (!msg.mMeta.mAuthorId.isNull())
{
CreateGxsForumMsg *cfm = new CreateGxsForumMsg(groupId(), msg.mMeta.mParentId, msg.mMeta.mMsgId, msg.mMeta.mAuthorId);
cfm->insertPastedText(QString::fromUtf8(msg.mMsg.c_str())) ;
cfm->show();
/* window will destroy itself! */
}
else
{
QMessageBox::information(this, tr("RetroShare"),tr("You cant reply to an Anonymous Author"));
}
}
void GxsForumThreadWidget::replyForumMessageData(const RsGxsForumMsg &msg) void GxsForumThreadWidget::replyForumMessageData(const RsGxsForumMsg &msg)
{ {
if ((msg.mMeta.mGroupId != groupId()) || (msg.mMeta.mMsgId != mThreadId)) if ((msg.mMeta.mGroupId != groupId()) || (msg.mMeta.mMsgId != mThreadId))
@ -2093,10 +2205,12 @@ void GxsForumThreadWidget::replyForumMessageData(const RsGxsForumMsg &msg)
if (!msg.mMeta.mAuthorId.isNull()) if (!msg.mMeta.mAuthorId.isNull())
{ {
CreateGxsForumMsg *cfm = new CreateGxsForumMsg(groupId(), mThreadId); CreateGxsForumMsg *cfm = new CreateGxsForumMsg(groupId(), mThreadId,RsGxsMessageId());
QTextDocument doc ;
// QTextDocument doc ;
// doc.setHtml(QString::fromUtf8(msg.mMsg.c_str()) ); // doc.setHtml(QString::fromUtf8(msg.mMsg.c_str()) );
// std::string cited_text(doc.toPlainText().toStdString()) ; // std::string cited_text(doc.toPlainText().toStdString()) ;
RsHtml::makeQuotedText(ui->postText); RsHtml::makeQuotedText(ui->postText);
cfm->insertPastedText(RsHtml::makeQuotedText(ui->postText)) ; cfm->insertPastedText(RsHtml::makeQuotedText(ui->postText)) ;
@ -2317,7 +2431,8 @@ void GxsForumThreadWidget::loadMessageData(const uint32_t &token)
/*********************** **** **** **** ***********************/ /*********************** **** **** **** ***********************/
/*********************** **** **** **** ***********************/ /*********************** **** **** **** ***********************/
void GxsForumThreadWidget::requestMsgData_ReplyMessage(const RsGxsGrpMsgIdPair &msgId)
void GxsForumThreadWidget::requestMsgData_ReplyWithPrivateMessage(const RsGxsGrpMsgIdPair &msgId)
{ {
RsTokReqOptions opts; RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
@ -2352,7 +2467,23 @@ void GxsForumThreadWidget::requestMsgData_ShowAuthorInPeople(const RsGxsGrpMsgId
uint32_t token; uint32_t token;
mTokenQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, mTokenTypeShowAuthorInPeople); mTokenQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, mTokenTypeShowAuthorInPeople);
} }
void GxsForumThreadWidget::requestMsgData_EditForumMessage(const RsGxsGrpMsgIdPair &msgId)
{
RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
#ifdef DEBUG_FORUMS
std::cerr << "GxsForumThreadWidget::requestMsgData_ReplyMessage(" << msgId.first << "," << msgId.second << ")";
std::cerr << std::endl;
#endif
GxsMsgReq msgIds;
std::vector<RsGxsMessageId> &vect = msgIds[msgId.first];
vect.push_back(msgId.second);
uint32_t token;
mTokenQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, mTokenTypeEditForumMessage);
}
void GxsForumThreadWidget::requestMsgData_ReplyForumMessage(const RsGxsGrpMsgIdPair &msgId) void GxsForumThreadWidget::requestMsgData_ReplyForumMessage(const RsGxsGrpMsgIdPair &msgId)
{ {
RsTokReqOptions opts; RsTokReqOptions opts;
@ -2396,6 +2527,31 @@ void GxsForumThreadWidget::loadMsgData_ReplyMessage(const uint32_t &token)
} }
} }
void GxsForumThreadWidget::loadMsgData_EditForumMessage(const uint32_t &token)
{
#ifdef DEBUG_FORUMS
std::cerr << "GxsForumThreadWidget::loadMsgData_EditMessage()";
std::cerr << std::endl;
#endif
std::vector<RsGxsForumMsg> msgs;
if (rsGxsForums->getMsgData(token, msgs))
{
if (msgs.size() != 1)
{
std::cerr << "GxsForumThreadWidget::loadMsgData_EditMessage() ERROR Wrong number of answers";
std::cerr << std::endl;
return;
}
editForumMessageData(msgs[0]);
}
else
{
std::cerr << "GxsForumThreadWidget::loadMsgData_ReplyMessage() ERROR Missing Message Data...";
std::cerr << std::endl;
}
}
void GxsForumThreadWidget::loadMsgData_ReplyForumMessage(const uint32_t &token) void GxsForumThreadWidget::loadMsgData_ReplyForumMessage(const uint32_t &token)
{ {
#ifdef DEBUG_FORUMS #ifdef DEBUG_FORUMS
@ -2523,6 +2679,10 @@ void GxsForumThreadWidget::loadRequest(const TokenQueue *queue, const TokenReque
return; return;
} }
if (req.mUserType == mTokenTypeEditForumMessage) {
loadMsgData_EditForumMessage(req.mToken);
return;
}
if (req.mUserType == mTokenTypeShowAuthorInPeople) { if (req.mUserType == mTokenTypeShowAuthorInPeople) {
loadMsgData_ShowAuthorInPeople(req.mToken); loadMsgData_ShowAuthorInPeople(req.mToken);
return; return;

View file

@ -1,6 +1,8 @@
#ifndef GXSFORUMTHREADWIDGET_H #ifndef GXSFORUMTHREADWIDGET_H
#define GXSFORUMTHREADWIDGET_H #define GXSFORUMTHREADWIDGET_H
#include <QMap>
#include "gui/gxs/GxsMessageFrameWidget.h" #include "gui/gxs/GxsMessageFrameWidget.h"
#include <retroshare/rsgxsforums.h> #include <retroshare/rsgxsforums.h>
#include "gui/gxs/GxsIdDetails.h" #include "gui/gxs/GxsIdDetails.h"
@ -73,12 +75,15 @@ private slots:
void contextMenuTextBrowser(QPoint point); void contextMenuTextBrowser(QPoint point);
void changedThread(); void changedThread();
void changedVersion();
void clickedThread (QTreeWidgetItem *item, int column); void clickedThread (QTreeWidgetItem *item, int column);
void replytomessage(); void reply_with_private_message();
void replytoforummessage(); void replytoforummessage();
void editforummessage();
void replyMessageData(const RsGxsForumMsg &msg); void replyMessageData(const RsGxsForumMsg &msg);
void editForumMessageData(const RsGxsForumMsg &msg);
void replyForumMessageData(const RsGxsForumMsg &msg); void replyForumMessageData(const RsGxsForumMsg &msg);
void showAuthorInPeople(const RsGxsForumMsg& msg); void showAuthorInPeople(const RsGxsForumMsg& msg);
@ -147,19 +152,22 @@ private:
static void loadAuthorIdCallback(GxsIdDetailsType type, const RsIdentityDetails &details, QObject *object, const QVariant &/*data*/); static void loadAuthorIdCallback(GxsIdDetailsType type, const RsIdentityDetails &details, QObject *object, const QVariant &/*data*/);
void requestMessageData(const RsGxsGrpMsgIdPair &msgId); void requestMessageData(const RsGxsGrpMsgIdPair &msgId);
void requestMsgData_ReplyMessage(const RsGxsGrpMsgIdPair &msgId); void requestMsgData_ReplyWithPrivateMessage(const RsGxsGrpMsgIdPair &msgId);
void requestMsgData_ShowAuthorInPeople(const RsGxsGrpMsgIdPair &msgId); void requestMsgData_ShowAuthorInPeople(const RsGxsGrpMsgIdPair &msgId);
void requestMsgData_ReplyForumMessage(const RsGxsGrpMsgIdPair &msgId); void requestMsgData_ReplyForumMessage(const RsGxsGrpMsgIdPair &msgId);
void requestMsgData_EditForumMessage(const RsGxsGrpMsgIdPair &msgId);
void loadMessageData(const uint32_t &token); void loadMessageData(const uint32_t &token);
void loadMsgData_ReplyMessage(const uint32_t &token); void loadMsgData_ReplyMessage(const uint32_t &token);
void loadMsgData_ReplyForumMessage(const uint32_t &token); void loadMsgData_ReplyForumMessage(const uint32_t &token);
void loadMsgData_EditForumMessage(const uint32_t &token);
void loadMsgData_ShowAuthorInPeople(const uint32_t &token); void loadMsgData_ShowAuthorInPeople(const uint32_t &token);
void loadMsgData_SetAuthorOpinion(const uint32_t &token, RsReputations::Opinion opinion); void loadMsgData_SetAuthorOpinion(const uint32_t &token, RsReputations::Opinion opinion);
private: private:
RsGxsGroupId mLastForumID; RsGxsGroupId mLastForumID;
RsGxsMessageId mThreadId; RsGxsMessageId mThreadId;
RsGxsMessageId mOrigThreadId;
RsGxsForumGroup mForumGroup; RsGxsForumGroup mForumGroup;
QString mForumDescription; QString mForumDescription;
int mSubscribeFlags; int mSubscribeFlags;
@ -177,6 +185,7 @@ private:
uint32_t mTokenTypeMessageData; uint32_t mTokenTypeMessageData;
uint32_t mTokenTypeReplyMessage; uint32_t mTokenTypeReplyMessage;
uint32_t mTokenTypeReplyForumMessage; uint32_t mTokenTypeReplyForumMessage;
uint32_t mTokenTypeEditForumMessage;
uint32_t mTokenTypeShowAuthorInPeople; uint32_t mTokenTypeShowAuthorInPeople;
uint32_t mTokenTypeNegativeAuthor; uint32_t mTokenTypeNegativeAuthor;
uint32_t mTokenTypePositiveAuthor; uint32_t mTokenTypePositiveAuthor;
@ -192,6 +201,8 @@ private:
RsGxsMessageId mNavigatePendingMsgId; RsGxsMessageId mNavigatePendingMsgId;
QList<RsGxsMessageId> mIgnoredMsgId; QList<RsGxsMessageId> mIgnoredMsgId;
QMap<RsGxsMessageId,QVector<QPair<time_t,RsGxsMessageId> > > mPostVersions ; // holds older versions of posts
Ui::GxsForumThreadWidget *ui; Ui::GxsForumThreadWidget *ui;
}; };

View file

@ -289,14 +289,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="7"> <item row="0" column="13">
<widget class="QLabel" name="time_label">
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
<item row="0" column="12">
<widget class="QPushButton" name="nextUnreadButton"> <widget class="QPushButton" name="nextUnreadButton">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed"> <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
@ -332,7 +325,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="14"> <item row="0" column="15">
<widget class="QPushButton" name="expandButton"> <widget class="QPushButton" name="expandButton">
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
@ -372,7 +365,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="11"> <item row="0" column="12">
<spacer name="postHSpacer"> <spacer name="postHSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
@ -464,20 +457,30 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="10"> <item row="0" column="11">
<widget class="GxsIdLabel" name="by_label"> <widget class="GxsIdLabel" name="by_label">
<property name="text"> <property name="text">
<string notr="true"/> <string notr="true"/>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="9"> <item row="0" column="10">
<widget class="QLabel" name="by_text_label"> <widget class="QLabel" name="by_text_label">
<property name="text"> <property name="text">
<string>By </string> <string>By </string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="9">
<widget class="QComboBox" name="versions_CB"/>
</item>
<item row="0" column="7">
<widget class="QLabel" name="time_label">
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
</layout> </layout>
@ -562,8 +565,8 @@
</customwidget> </customwidget>
</customwidgets> </customwidgets>
<resources> <resources>
<include location="../images.qrc"/>
<include location="../icons.qrc"/> <include location="../icons.qrc"/>
<include location="../images.qrc"/>
</resources> </resources>
<connections/> <connections/>
</ui> </ui>

View file

@ -89,6 +89,8 @@ void GxsForumsFillThread::calculateExpand(const RsGxsForumMsg &msg, QTreeWidgetI
} }
} }
static bool decreasing_time_comp(const QPair<time_t,RsGxsMessageId>& e1,const QPair<time_t,RsGxsMessageId>& e2) { return e2.first < e1.first ; }
void GxsForumsFillThread::run() void GxsForumsFillThread::run()
{ {
RsTokenService *service = rsGxsForums->getTokenService(); RsTokenService *service = rsGxsForums->getTokenService();
@ -171,7 +173,7 @@ void GxsForumsFillThread::run()
int pos = 0; int pos = 0;
int steps = count / PROGRESSBAR_MAX; int steps = count / PROGRESSBAR_MAX;
int step = 0; int step = 0;
// ThreadList contains the list of parent threads. The algorithm below iterates through all messages // ThreadList contains the list of parent threads. The algorithm below iterates through all messages
// and tries to establish parenthood relationships between them, given that we only know the // and tries to establish parenthood relationships between them, given that we only know the
// immediate parent of a message and now its children. Some messages have a missing parent and for them // immediate parent of a message and now its children. Some messages have a missing parent and for them
@ -185,6 +187,99 @@ void GxsForumsFillThread::run()
std::map<RsGxsMessageId,std::list<RsGxsMessageId> > kids_array ; std::map<RsGxsMessageId,std::list<RsGxsMessageId> > kids_array ;
std::set<RsGxsMessageId> missing_parents; std::set<RsGxsMessageId> missing_parents;
// First of all, remove all older versions of posts. This is done by first adding all posts into a hierarchy structure
// and then removing all posts which have a new versions available. The older versions are kept appart.
#ifdef DEBUG_FORUMS
std::cerr << "GxsForumsFillThread::run() Collecting post versions" << std::endl;
#endif
mPostVersions.clear();
std::list<RsGxsMessageId> msg_stack ;
for ( std::map<RsGxsMessageId,RsGxsForumMsg>::iterator msgIt = msgs.begin(); msgIt != msgs.end();++msgIt)
if(!msgIt->second.mMeta.mOrigMsgId.isNull() && msgIt->second.mMeta.mOrigMsgId != msgIt->second.mMeta.mMsgId)
{
#ifdef DEBUG_FORUMS
std::cerr << " Post " << msgIt->second.mMeta.mMsgId << " is a new version of " << msgIt->second.mMeta.mOrigMsgId << std::endl;
#endif
std::map<RsGxsMessageId,RsGxsForumMsg>::iterator msgIt2 = msgs.find(msgIt->second.mMeta.mOrigMsgId);
// Ensuring that the post exists allows to only collect the existing data.
if(msgIt2 == msgs.end())
continue ;
// Make sure that the author is the same than the original message. This should always happen, but nothing can prevent someone to
// craft a new version of a message with his own signature.
if(msgIt2->second.mMeta.mAuthorId != msgIt->second.mMeta.mAuthorId)
continue ;
// always add the post a self version
if(mPostVersions[msgIt->second.mMeta.mOrigMsgId].empty())
mPostVersions[msgIt->second.mMeta.mOrigMsgId].push_back(QPair<time_t,RsGxsMessageId>(msgIt2->second.mMeta.mPublishTs,msgIt2->second.mMeta.mMsgId)) ;
mPostVersions[msgIt->second.mMeta.mOrigMsgId].push_back(QPair<time_t,RsGxsMessageId>(msgIt->second.mMeta.mPublishTs,msgIt->second.mMeta.mMsgId)) ;
}
// The following code assembles all new versions of a given post into the same array, indexed by the oldest version of the post.
for(QMap<RsGxsMessageId,QVector<QPair<time_t,RsGxsMessageId> > >::iterator it(mPostVersions.begin());it!=mPostVersions.end();++it)
{
QVector<QPair<time_t,RsGxsMessageId> >& v(*it) ;
for(int32_t i=0;i<v.size();++i)
if(v[i].second != it.key())
{
RsGxsMessageId sub_msg_id = v[i].second ;
QMap<RsGxsMessageId,QVector<QPair<time_t,RsGxsMessageId> > >::iterator it2 = mPostVersions.find(sub_msg_id);
if(it2 != mPostVersions.end())
{
for(int32_t j=0;j<(*it2).size();++j)
if((*it2)[j].second != sub_msg_id) // dont copy it, since it is already present at slot i
v.append((*it2)[j]) ;
mPostVersions.erase(it2) ; // it2 is never equal to it
}
}
}
// Now remove from msg ids, all posts except the most recent one. And make the mPostVersion be indexed by the most recent version of the post,
// which corresponds to the item in the tree widget.
#ifdef DEBUG_FORUMS
std::cerr << "Final post versions: " << std::endl;
#endif
QMap<RsGxsMessageId,QVector<QPair<time_t,RsGxsMessageId> > > mTmp;
for(QMap<RsGxsMessageId,QVector<QPair<time_t,RsGxsMessageId> > >::iterator it(mPostVersions.begin());it!=mPostVersions.end();++it)
{
#ifdef DEBUG_FORUMS
std::cerr << "Original post: " << it.key() << std::endl;
#endif
// Finally, sort the posts from newer to older
qSort((*it).begin(),(*it).end(),decreasing_time_comp) ;
#ifdef DEBUG_FORUMS
std::cerr << " most recent version " << (*it)[0].first << " " << (*it)[0].second << std::endl;
#endif
for(int32_t i=1;i<(*it).size();++i)
{
msgs.erase((*it)[i].second) ;
#ifdef DEBUG_FORUMS
std::cerr << " older version " << (*it)[i].first << " " << (*it)[i].second << std::endl;
#endif
}
mTmp[(*it)[0].second] = *it ; // index the versions map by the ID of the most recent post.
}
mPostVersions = mTmp ;
// The first step is to find the top level thread messages. These are defined as the messages without // The first step is to find the top level thread messages. These are defined as the messages without
// any parent message ID. // any parent message ID.
@ -194,6 +289,8 @@ void GxsForumsFillThread::run()
std::map<RsGxsMessageId,RsGxsForumMsg> kept_msgs; std::map<RsGxsMessageId,RsGxsForumMsg> kept_msgs;
for ( std::map<RsGxsMessageId,RsGxsForumMsg>::iterator msgIt = msgs.begin(); msgIt != msgs.end();++msgIt) for ( std::map<RsGxsMessageId,RsGxsForumMsg>::iterator msgIt = msgs.begin(); msgIt != msgs.end();++msgIt)
{
if(mFlatView || msgIt->second.mMeta.mParentId.isNull()) if(mFlatView || msgIt->second.mMeta.mParentId.isNull())
{ {
@ -234,9 +331,12 @@ void GxsForumsFillThread::run()
kids_array[msgIt->second.mMeta.mParentId].push_back(msgIt->first) ; kids_array[msgIt->second.mMeta.mParentId].push_back(msgIt->first) ;
kept_msgs.insert(*msgIt) ; kept_msgs.insert(*msgIt) ;
} }
}
msgs = kept_msgs; msgs = kept_msgs;
// Also create a list of posts by time, when they are new versions of existing posts. Only the last one will have an item created.
// Add a fake toplevel item for the parent IDs that we dont actually have. // Add a fake toplevel item for the parent IDs that we dont actually have.
for(std::set<RsGxsMessageId>::const_iterator it(missing_parents.begin());it!=missing_parents.end();++it) for(std::set<RsGxsMessageId>::const_iterator it(missing_parents.begin());it!=missing_parents.end();++it)

Some files were not shown because too many files have changed in this diff Show more