From 93aeae0f59963dc895ef0a5cae2fba8036a4a703 Mon Sep 17 00:00:00 2001 From: Konrad Date: Fri, 14 Apr 2017 17:41:35 +0200 Subject: [PATCH 01/39] Added: Handling requests to delete identity --- libresapi/src/api/IdentityHandler.cpp | 39 ++++++++++++++++++++++++++- libresapi/src/api/IdentityHandler.h | 1 + 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/libresapi/src/api/IdentityHandler.cpp b/libresapi/src/api/IdentityHandler.cpp index 1a43211ea..bf1c65911 100644 --- a/libresapi/src/api/IdentityHandler.cpp +++ b/libresapi/src/api/IdentityHandler.cpp @@ -95,6 +95,37 @@ protected: } }; +class DeleteIdentityTask : public GxsResponseTask +{ +public: + DeleteIdentityTask(RsIdentity* idservice) : + GxsResponseTask(idservice, idservice->getTokenService()), + mToken(0), + mRsIdentity(idservice) + {} + +protected: + virtual void gxsDoWork(Request &req, Response &resp) + { + RsGxsIdGroup group; + std::string gxs_id; + + req.mStream << makeKeyValueReference("gxs_id", gxs_id); + group.mMeta.mGroupId = RsGxsGroupId(gxs_id); + + mRsIdentity->deleteIdentity(mToken, group); + addWaitingToken(mToken); + + done(); + return; + } + +private: + uint32_t mToken; + RsIdentity* mRsIdentity; + RsGxsId mId; +}; + IdentityHandler::IdentityHandler(StateTokenServer *sts, RsNotify *notify, RsIdentity *identity): mStateTokenServer(sts), mNotify(notify), mRsIdentity(identity), mMtx("IdentityHandler Mtx"), mStateToken(sts->getNewToken()) @@ -107,7 +138,8 @@ IdentityHandler::IdentityHandler(StateTokenServer *sts, RsNotify *notify, RsIden addResourceHandler("own_ids", this, &IdentityHandler::handleOwnIdsRequest); addResourceHandler("notown_ids", this, &IdentityHandler::handleNotOwnIdsRequest); - addResourceHandler("create_identity", this, &IdentityHandler::handleCreateIdentity); + addResourceHandler("create_identity", this, &IdentityHandler::handleCreateIdentity); + addResourceHandler("delete_identity", this, &IdentityHandler::handleDeleteIdentity); } IdentityHandler::~IdentityHandler() @@ -302,4 +334,9 @@ ResponseTask* IdentityHandler::handleCreateIdentity(Request & /* req */, Respons return new CreateIdentityTask(mRsIdentity); } +ResponseTask* IdentityHandler::handleDeleteIdentity(Request& req, Response& resp) +{ + return new DeleteIdentityTask(mRsIdentity); +} + } // namespace resource_api diff --git a/libresapi/src/api/IdentityHandler.h b/libresapi/src/api/IdentityHandler.h index 1b54f5438..17f7cb37d 100644 --- a/libresapi/src/api/IdentityHandler.h +++ b/libresapi/src/api/IdentityHandler.h @@ -28,6 +28,7 @@ private: ResponseTask *handleOwn(Request& req, Response& resp); ResponseTask *handleCreateIdentity(Request& req, Response& resp); + ResponseTask *handleDeleteIdentity(Request& req, Response& resp); StateTokenServer* mStateTokenServer; RsNotify* mNotify; From fd33315146d86bca139c8a0fb5ccd9ec39d57e38 Mon Sep 17 00:00:00 2001 From: Konrad Date: Fri, 14 Apr 2017 17:44:17 +0200 Subject: [PATCH 02/39] Added: Handling requests to create lobby --- libresapi/src/api/ChatHandler.cpp | 34 +++++++++++++++++++++++++++++++ libresapi/src/api/ChatHandler.h | 1 + 2 files changed, 35 insertions(+) diff --git a/libresapi/src/api/ChatHandler.cpp b/libresapi/src/api/ChatHandler.cpp index f576f8601..6e7fa07fe 100644 --- a/libresapi/src/api/ChatHandler.cpp +++ b/libresapi/src/api/ChatHandler.cpp @@ -145,6 +145,7 @@ ChatHandler::ChatHandler(StateTokenServer *sts, RsNotify *notify, RsMsgs *msgs, addResourceHandler("*", this, &ChatHandler::handleWildcard); addResourceHandler("lobbies", this, &ChatHandler::handleLobbies); + addResourceHandler("create_lobby", this, &ChatHandler::handleCreateLobby); addResourceHandler("subscribe_lobby", this, &ChatHandler::handleSubscribeLobby); addResourceHandler("unsubscribe_lobby", this, &ChatHandler::handleUnsubscribeLobby); addResourceHandler("autosubscribe_lobby", this, &ChatHandler::handleAutoSubsribeLobby); @@ -1210,4 +1211,37 @@ void ChatHandler::handleCloseDistantChatConnexion(Request& req, Response& resp) else resp.setFail("Failed to close distant chat"); } +void ChatHandler::handleCreateLobby(Request& req, Response& resp) +{ + std::set invited_identites; + std::string lobby_name; + std::string lobby_topic; + std::string gxs_id; + + req.mStream << makeKeyValueReference("lobby_name", lobby_name); + req.mStream << makeKeyValueReference("lobby_topic", lobby_topic); + req.mStream << makeKeyValueReference("gxs_id", gxs_id); + + RsGxsId gxsId(gxs_id); + + bool lobby_public; + bool pgp_signed; + + req.mStream << makeKeyValueReference("lobby_public", lobby_public); + req.mStream << makeKeyValueReference("pgp_signed", pgp_signed); + + ChatLobbyFlags lobby_flags; + + if(lobby_public) + lobby_flags |= RS_CHAT_LOBBY_FLAGS_PUBLIC; + + if(pgp_signed) + lobby_flags |= RS_CHAT_LOBBY_FLAGS_PGP_SIGNED; + + mRsMsgs->createChatLobby(lobby_name, gxsId, lobby_topic, invited_identites, lobby_flags); + + tick(); + resp.setOk(); +} + } // namespace resource_api diff --git a/libresapi/src/api/ChatHandler.h b/libresapi/src/api/ChatHandler.h index 3463cee57..9cda3e551 100644 --- a/libresapi/src/api/ChatHandler.h +++ b/libresapi/src/api/ChatHandler.h @@ -118,6 +118,7 @@ public: private: void handleWildcard(Request& req, Response& resp); void handleLobbies(Request& req, Response& resp); + void handleCreateLobby(Request& req, Response& resp); void handleSubscribeLobby(Request& req, Response& resp); void handleUnsubscribeLobby(Request& req, Response& resp); void handleAutoSubsribeLobby(Request& req, Response& resp); From 4a99000f1624b0ef9f3a46cb7a4ad7d7f6791104 Mon Sep 17 00:00:00 2001 From: Konrad Date: Tue, 18 Apr 2017 14:00:30 +0200 Subject: [PATCH 03/39] Added: Handling requests to get and set node options --- libresapi/src/api/PeersHandler.cpp | 198 +++++++++++++++++++++++++++++ libresapi/src/api/PeersHandler.h | 3 + 2 files changed, 201 insertions(+) diff --git a/libresapi/src/api/PeersHandler.cpp b/libresapi/src/api/PeersHandler.cpp index 8473bce04..3ba827a33 100644 --- a/libresapi/src/api/PeersHandler.cpp +++ b/libresapi/src/api/PeersHandler.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -106,6 +107,84 @@ bool peerInfoToStream(StreamBase& stream, RsPeerDetails& details, RsPeers* peers return ok; } +std::string peerStateString(int peerState) +{ + if (peerState & RS_PEER_STATE_CONNECTED) { + return "Connected"; + } else if (peerState & RS_PEER_STATE_UNREACHABLE) { + return "Unreachable"; + } else if (peerState & RS_PEER_STATE_ONLINE) { + return "Available"; + } else if (peerState & RS_PEER_STATE_FRIEND) { + return "Offline"; + } + + return "Neighbor"; +} + +std::string connectStateString(RsPeerDetails &details) +{ + std::string stateString; + bool isConnected = false; + + switch (details.connectState) { + case 0: + stateString = peerStateString(details.state); + break; + case RS_PEER_CONNECTSTATE_TRYING_TCP: + stateString = "Trying TCP"; + break; + case RS_PEER_CONNECTSTATE_TRYING_UDP: + stateString = "Trying UDP"; + break; + case RS_PEER_CONNECTSTATE_CONNECTED_TCP: + stateString = "Connected: TCP"; + isConnected = true; + break; + case RS_PEER_CONNECTSTATE_CONNECTED_UDP: + stateString = "Connected: UDP"; + isConnected = true; + break; + case RS_PEER_CONNECTSTATE_CONNECTED_TOR: + stateString = "Connected: Tor"; + isConnected = true; + break; + case RS_PEER_CONNECTSTATE_CONNECTED_I2P: + stateString = "Connected: I2P"; + isConnected = true; + break; + case RS_PEER_CONNECTSTATE_CONNECTED_UNKNOWN: + stateString = "Connected: Unknown"; + isConnected = true; + break; + } + + if(isConnected) { + stateString += " "; + if(details.actAsServer) + stateString += "inbound connection"; + else + stateString += "outbound connection"; + } + + if (details.connectStateString.empty() == false) { + if (stateString.empty() == false) { + stateString += ": "; + } + stateString += details.connectStateString; + } + + /* HACK to display DHT Status info too */ + if (details.foundDHT) { + if (stateString.empty() == false) { + stateString += ", "; + } + stateString += "DHT: Contact"; + } + + return stateString; +} + PeersHandler::PeersHandler(StateTokenServer* sts, RsNotify* notify, RsPeers *peers, RsMsgs* msgs): mStateTokenServer(sts), mNotify(notify), @@ -121,6 +200,8 @@ PeersHandler::PeersHandler(StateTokenServer* sts, RsNotify* notify, RsPeers *pee addResourceHandler("set_custom_state_string", this, &PeersHandler::handleSetCustomStateString); addResourceHandler("get_pgp_options", this, &PeersHandler::handleGetPGPOptions); addResourceHandler("set_pgp_options", this, &PeersHandler::handleSetPGPOptions); + addResourceHandler("get_node_options", this, &PeersHandler::handleGetNodeOptions); + addResourceHandler("set_node_options", this, &PeersHandler::handleSetNodeOptions); addResourceHandler("examine_cert", this, &PeersHandler::handleExamineCert); } @@ -645,6 +726,123 @@ void PeersHandler::handleSetPGPOptions(Request& req, Response& resp) resp.setOk(); } +void PeersHandler::handleGetNodeOptions(Request& req, Response& resp) +{ + std::string peer_id; + req.mStream << makeKeyValueReference("peer_id", peer_id); + + RsPeerId peerId(peer_id); + RsPeerDetails detail; + if(!mRsPeers->getPeerDetails(peerId, detail)) + { + resp.setFail(); + return; + } + + resp.mDataStream << makeKeyValue("peer_id", detail.id.toStdString()); + resp.mDataStream << makeKeyValue("name", detail.name); + resp.mDataStream << makeKeyValue("location", detail.location); + resp.mDataStream << makeKeyValue("pgp_id", detail.gpg_id.toStdString()); + resp.mDataStream << makeKeyValue("last_contact", detail.lastConnect); + + std::string status_message = mRsMsgs->getCustomStateString(detail.id); + resp.mDataStream << makeKeyValueReference("status_message", status_message); + + std::string encryption; + RsPeerCryptoParams cdet; + if(RsControl::instance()->getPeerCryptoDetails(detail.id, cdet) && cdet.connexion_state != 0) + { + encryption = cdet.cipher_version; + encryption += ": "; + encryption += cdet.cipher_name; + + if(cdet.cipher_version != "TLSv1.2") + encryption += cdet.cipher_bits_1; + } + else + encryption = "Not connected"; + + resp.mDataStream << makeKeyValueReference("encryption", encryption); + + resp.mDataStream << makeKeyValue("is_hidden_node", detail.isHiddenNode); + if (detail.isHiddenNode) + { + resp.mDataStream << makeKeyValue("local_address", detail.hiddenNodeAddress); + resp.mDataStream << makeKeyValue("local_port", (int)detail.hiddenNodePort); + resp.mDataStream << makeKeyValue("ext_address", std::string("none")); + resp.mDataStream << makeKeyValue("ext_port", 0); + resp.mDataStream << makeKeyValue("dyn_dns", std::string("none")); + } + else + { + resp.mDataStream << makeKeyValue("local_address", detail.localAddr); + resp.mDataStream << makeKeyValue("local_port", (int)detail.localPort); + resp.mDataStream << makeKeyValue("ext_address", detail.extAddr); + resp.mDataStream << makeKeyValue("ext_port", (int)detail.extPort); + resp.mDataStream << makeKeyValue("dyn_dns", detail.dyndns); + } + + resp.mDataStream << makeKeyValue("connection_status", connectStateString(detail)); + + StreamBase& addressesStream = resp.mDataStream.getStreamToMember("ip_addresses"); + + // mark as list (in case list is empty) + addressesStream.getStreamToMember(); + + for(std::list::const_iterator it(detail.ipAddressList.begin()); it != detail.ipAddressList.end(); ++it) + { + addressesStream.getStreamToMember() << makeKeyValue("ip_address", (*it)); + } + + std::string certificate = mRsPeers->GetRetroshareInvite(detail.id, false); + resp.mDataStream << makeKeyValueReference("certificate", certificate); + + resp.setOk(); +} + +void PeersHandler::handleSetNodeOptions(Request& req, Response& resp) +{ + std::string peer_id; + req.mStream << makeKeyValueReference("peer_id", peer_id); + + RsPeerId peerId(peer_id); + RsPeerDetails detail; + if(!mRsPeers->getPeerDetails(peerId, detail)) + { + resp.setFail(); + return; + } + + std::string local_address; + std::string ext_address; + std::string dyn_dns; + int local_port; + int ext_port; + + req.mStream << makeKeyValueReference("local_address", local_address); + req.mStream << makeKeyValueReference("local_port", local_port); + req.mStream << makeKeyValueReference("ext_address", ext_address); + req.mStream << makeKeyValueReference("ext_port", ext_port); + req.mStream << makeKeyValueReference("dyn_dns", dyn_dns); + + if(!detail.isHiddenNode) + { + if(detail.localAddr != local_address || (int)detail.localPort != local_port) + mRsPeers->setLocalAddress(peerId, local_address, local_port); + if(detail.extAddr != ext_address || (int)detail.extPort != ext_port) + mRsPeers->setExtAddress(peerId, ext_address, ext_port); + if(detail.dyndns != dyn_dns) + mRsPeers->setDynDNS(peerId, dyn_dns); + } + else + { + if(detail.hiddenNodeAddress != local_address || detail.hiddenNodePort != local_port) + rsPeers->setHiddenNode(peerId, local_address, local_port); + } + + resp.setOk(); +} + StateToken PeersHandler::getCurrentStateToken() { RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ diff --git a/libresapi/src/api/PeersHandler.h b/libresapi/src/api/PeersHandler.h index 5ae393b2f..a7386d8c9 100644 --- a/libresapi/src/api/PeersHandler.h +++ b/libresapi/src/api/PeersHandler.h @@ -44,6 +44,9 @@ private: void handleGetPGPOptions(Request& req, Response& resp); void handleSetPGPOptions(Request& req, Response& resp); + void handleGetNodeOptions(Request& req, Response& resp); + void handleSetNodeOptions(Request& req, Response& resp); + // a helper which ensures proper mutex locking StateToken getCurrentStateToken(); From 76dd7fe47fce9d91065894503013e00f6e5d29a0 Mon Sep 17 00:00:00 2001 From: Konrad Date: Tue, 18 Apr 2017 14:02:14 +0200 Subject: [PATCH 04/39] Added: Handling requests to add and remove contact --- libresapi/src/api/IdentityHandler.cpp | 33 +++++++++++++++++++++++++++ libresapi/src/api/IdentityHandler.h | 3 +++ 2 files changed, 36 insertions(+) diff --git a/libresapi/src/api/IdentityHandler.cpp b/libresapi/src/api/IdentityHandler.cpp index bf1c65911..529188087 100644 --- a/libresapi/src/api/IdentityHandler.cpp +++ b/libresapi/src/api/IdentityHandler.cpp @@ -138,6 +138,9 @@ IdentityHandler::IdentityHandler(StateTokenServer *sts, RsNotify *notify, RsIden addResourceHandler("own_ids", this, &IdentityHandler::handleOwnIdsRequest); addResourceHandler("notown_ids", this, &IdentityHandler::handleNotOwnIdsRequest); + addResourceHandler("add_contact", this, &IdentityHandler::handleAddContact); + addResourceHandler("remove_contact", this, &IdentityHandler::handleRemoveContact); + addResourceHandler("create_identity", this, &IdentityHandler::handleCreateIdentity); addResourceHandler("delete_identity", this, &IdentityHandler::handleDeleteIdentity); } @@ -314,6 +317,36 @@ void IdentityHandler::handleOwnIdsRequest(Request & /*req*/, Response &resp) else resp.setFail(); } +void IdentityHandler::handleAddContact(Request& req, Response& resp) +{ + std::string gxs_id; + req.mStream << makeKeyValueReference("gxs_id", gxs_id); + + mRsIdentity->setAsRegularContact(RsGxsId(gxs_id), true); + + { + RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ + mStateTokenServer->replaceToken(mStateToken); + } + + resp.setOk(); +} + +void IdentityHandler::handleRemoveContact(Request& req, Response& resp) +{ + std::string gxs_id; + req.mStream << makeKeyValueReference("gxs_id", gxs_id); + + mRsIdentity->setAsRegularContact(RsGxsId(gxs_id), false); + + { + RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ + mStateTokenServer->replaceToken(mStateToken); + } + + resp.setOk(); +} + ResponseTask* IdentityHandler::handleOwn(Request & /* req */, Response &resp) { StateToken state; diff --git a/libresapi/src/api/IdentityHandler.h b/libresapi/src/api/IdentityHandler.h index 17f7cb37d..a164af365 100644 --- a/libresapi/src/api/IdentityHandler.h +++ b/libresapi/src/api/IdentityHandler.h @@ -26,6 +26,9 @@ private: void handleNotOwnIdsRequest(Request& req, Response& resp); void handleOwnIdsRequest(Request& req, Response& resp); + void handleAddContact(Request& req, Response& resp); + void handleRemoveContact(Request& req, Response& resp); + ResponseTask *handleOwn(Request& req, Response& resp); ResponseTask *handleCreateIdentity(Request& req, Response& resp); ResponseTask *handleDeleteIdentity(Request& req, Response& resp); From 3f54568d7fd324cc50c8bc4bdbefd56f943ca12a Mon Sep 17 00:00:00 2001 From: Konrad Date: Tue, 18 Apr 2017 22:56:35 +0200 Subject: [PATCH 05/39] Added: Handling requests to get details about identity --- libresapi/src/api/IdentityHandler.cpp | 125 ++++++++++++++++++++++++++ libresapi/src/api/IdentityHandler.h | 2 + 2 files changed, 127 insertions(+) diff --git a/libresapi/src/api/IdentityHandler.cpp b/libresapi/src/api/IdentityHandler.cpp index 529188087..097a04ef7 100644 --- a/libresapi/src/api/IdentityHandler.cpp +++ b/libresapi/src/api/IdentityHandler.cpp @@ -1,6 +1,7 @@ #include "IdentityHandler.h" #include +#include #include #include "Operators.h" @@ -143,6 +144,8 @@ IdentityHandler::IdentityHandler(StateTokenServer *sts, RsNotify *notify, RsIden addResourceHandler("create_identity", this, &IdentityHandler::handleCreateIdentity); addResourceHandler("delete_identity", this, &IdentityHandler::handleDeleteIdentity); + + addResourceHandler("get_identity_details", this, &IdentityHandler::handleGetIdentityDetails); } IdentityHandler::~IdentityHandler() @@ -347,6 +350,128 @@ void IdentityHandler::handleRemoveContact(Request& req, Response& resp) resp.setOk(); } +void IdentityHandler::handleGetIdentityDetails(Request& req, Response& resp) +{ + std::string gxs_id; + req.mStream << makeKeyValueReference("gxs_id", gxs_id); + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + uint32_t token; + + std::list groupIds; + groupIds.push_back(RsGxsGroupId(gxs_id)); + mRsIdentity->getTokenService()->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds); + + 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 + } + + RsGxsIdGroup data; + std::vector datavector; + if (!mRsIdentity->getGroupData(token, datavector)) + { + resp.setFail(); + return; + } + + data = datavector[0]; + + resp.mDataStream << makeKeyValue("gxs_name", data.mMeta.mGroupName); + resp.mDataStream << makeKeyValue("gxs_id", data.mMeta.mGroupId.toStdString()); + + resp.mDataStream << makeKeyValue("pgp_id_known", data.mPgpKnown); + resp.mDataStream << makeKeyValue("pgp_id", data.mPgpId.toStdString()); + + std::string pgp_name; + if (data.mPgpKnown) + { + RsPeerDetails details; + rsPeers->getGPGDetails(data.mPgpId, details); + pgp_name = details.name; + } + else + { + if (data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility) + pgp_name = "[Unknown node]"; + else + pgp_name = "Anonymous Id"; + } + resp.mDataStream << makeKeyValue("pgp_name", pgp_name); + + time_t now = time(NULL); + resp.mDataStream << makeKeyValue("last_usage", std::to_string(now - data.mLastUsageTS)); + + bool isAnonymous = false; + if(!data.mPgpKnown) + { + if (!(data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility)) + isAnonymous = true; + } + resp.mDataStream << makeKeyValue("anonymous", isAnonymous); + + + bool isOwnId = (data.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN); + resp.mDataStream << makeKeyValue("own", isOwnId); + + std::string type; + if(isOwnId) + { + if (data.mPgpKnown && !data.mPgpId.isNull()) + type = "Identity owned by you, linked to your Retroshare node"; + else + type = "Anonymous identity, owned by you"; + } + else if (data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility) + { + if (data.mPgpKnown) + { + if (rsPeers->isGPGAccepted(data.mPgpId)) + type = "Linked to a friend Retroshare node"; + else + type = "Linked to a known Retroshare node"; + } + else + type = "Linked to unknown Retroshare node"; + } + else + type = "Anonymous identity"; + + resp.mDataStream << makeKeyValue("type", type); + + resp.mDataStream << makeKeyValue("bannned_node", rsReputations->isNodeBanned(data.mPgpId)); + + RsReputations::ReputationInfo info; + rsReputations->getReputationInfo(RsGxsId(data.mMeta.mGroupId), data.mPgpId, info); + resp.mDataStream << makeKeyValue("friends_positive_votes", info.mFriendsPositiveVotes); + resp.mDataStream << makeKeyValue("friends_negative_votes", info.mFriendsNegativeVotes); + resp.mDataStream << makeKeyValue("overall_reputation_level", (int)info.mOverallReputationLevel); + resp.mDataStream << makeKeyValue("own_opinion", (int)info.mOwnOpinion); + + RsIdentityDetails details; + mRsIdentity->getIdDetails(RsGxsId(data.mMeta.mGroupId), details); + StreamBase& usagesStream = resp.mDataStream.getStreamToMember("usages"); + usagesStream.getStreamToMember(); + + for(std::map::const_iterator it(details.mUseCases.begin()); it != details.mUseCases.end(); ++it) + { + usagesStream.getStreamToMember() << makeKeyValue("usage_time", std::to_string(now - it->second)); + usagesStream.getStreamToMember() << makeKeyValue("usage_service", (int)(it->first.mServiceId)); + usagesStream.getStreamToMember() << makeKeyValue("usage_case", (int)(it->first.mUsageCode)); + } + + resp.setOk(); +} + ResponseTask* IdentityHandler::handleOwn(Request & /* req */, Response &resp) { StateToken state; diff --git a/libresapi/src/api/IdentityHandler.h b/libresapi/src/api/IdentityHandler.h index a164af365..0780585e8 100644 --- a/libresapi/src/api/IdentityHandler.h +++ b/libresapi/src/api/IdentityHandler.h @@ -29,6 +29,8 @@ private: void handleAddContact(Request& req, Response& resp); void handleRemoveContact(Request& req, Response& resp); + void handleGetIdentityDetails(Request& req, Response& resp); + ResponseTask *handleOwn(Request& req, Response& resp); ResponseTask *handleCreateIdentity(Request& req, Response& resp); ResponseTask *handleDeleteIdentity(Request& req, Response& resp); From 120ca9d0783d3dbbd8a7491b8fed3254a880c71f Mon Sep 17 00:00:00 2001 From: Konrad Date: Tue, 18 Apr 2017 22:58:15 +0200 Subject: [PATCH 06/39] Added: Handling requests to set opinion about identity --- libresapi/src/api/IdentityHandler.cpp | 15 +++++++++++++++ libresapi/src/api/IdentityHandler.h | 2 ++ 2 files changed, 17 insertions(+) diff --git a/libresapi/src/api/IdentityHandler.cpp b/libresapi/src/api/IdentityHandler.cpp index 097a04ef7..1b298467d 100644 --- a/libresapi/src/api/IdentityHandler.cpp +++ b/libresapi/src/api/IdentityHandler.cpp @@ -146,6 +146,8 @@ IdentityHandler::IdentityHandler(StateTokenServer *sts, RsNotify *notify, RsIden addResourceHandler("delete_identity", this, &IdentityHandler::handleDeleteIdentity); addResourceHandler("get_identity_details", this, &IdentityHandler::handleGetIdentityDetails); + + addResourceHandler("set_ban_node", this, &IdentityHandler::handleSetBanNode); } IdentityHandler::~IdentityHandler() @@ -472,6 +474,19 @@ void IdentityHandler::handleGetIdentityDetails(Request& req, Response& resp) resp.setOk(); } +void IdentityHandler::handleSetBanNode(Request& req, Response& resp) +{ + std::string pgp_id; + req.mStream << makeKeyValueReference("pgp_id", pgp_id); + RsPgpId pgpId(pgp_id); + + bool banned_node; + req.mStream << makeKeyValueReference("banned_node", banned_node); + rsReputations->banNode(pgpId, banned_node); + + resp.setOk(); +} + ResponseTask* IdentityHandler::handleOwn(Request & /* req */, Response &resp) { StateToken state; diff --git a/libresapi/src/api/IdentityHandler.h b/libresapi/src/api/IdentityHandler.h index 0780585e8..3824d483d 100644 --- a/libresapi/src/api/IdentityHandler.h +++ b/libresapi/src/api/IdentityHandler.h @@ -31,6 +31,8 @@ private: void handleGetIdentityDetails(Request& req, Response& resp); + void handleSetBanNode(Request& req, Response& resp); + ResponseTask *handleOwn(Request& req, Response& resp); ResponseTask *handleCreateIdentity(Request& req, Response& resp); ResponseTask *handleDeleteIdentity(Request& req, Response& resp); From b43bedf66948e1a5ff59b12d6af70c2a2b87617f Mon Sep 17 00:00:00 2001 From: Konrad Date: Tue, 18 Apr 2017 23:00:59 +0200 Subject: [PATCH 07/39] Added: Handling requests to set opinion about identity --- libresapi/src/api/IdentityHandler.cpp | 31 +++++++++++++++++++++++++++ libresapi/src/api/IdentityHandler.h | 1 + 2 files changed, 32 insertions(+) diff --git a/libresapi/src/api/IdentityHandler.cpp b/libresapi/src/api/IdentityHandler.cpp index 1b298467d..420d310a5 100644 --- a/libresapi/src/api/IdentityHandler.cpp +++ b/libresapi/src/api/IdentityHandler.cpp @@ -148,6 +148,7 @@ IdentityHandler::IdentityHandler(StateTokenServer *sts, RsNotify *notify, RsIden addResourceHandler("get_identity_details", this, &IdentityHandler::handleGetIdentityDetails); addResourceHandler("set_ban_node", this, &IdentityHandler::handleSetBanNode); + addResourceHandler("set_opinion", this, &IdentityHandler::handleSetOpinion); } IdentityHandler::~IdentityHandler() @@ -487,6 +488,36 @@ void IdentityHandler::handleSetBanNode(Request& req, Response& resp) resp.setOk(); } +void IdentityHandler::handleSetOpinion(Request& req, Response& resp) +{ + std::string gxs_id; + req.mStream << makeKeyValueReference("gxs_id", gxs_id); + RsGxsId gxsId(gxs_id); + + int own_opinion; + req.mStream << makeKeyValueReference("own_opinion", own_opinion); + + RsReputations::Opinion opinion; + switch(own_opinion) + { + case 0: + opinion = RsReputations::OPINION_NEGATIVE; + break; + case 1: opinion = + RsReputations::OPINION_NEUTRAL; + break; + case 2: + opinion = RsReputations::OPINION_POSITIVE; + break; + default: + resp.setFail(); + return; + } + rsReputations->setOwnOpinion(gxsId, opinion); + + resp.setOk(); +} + ResponseTask* IdentityHandler::handleOwn(Request & /* req */, Response &resp) { StateToken state; diff --git a/libresapi/src/api/IdentityHandler.h b/libresapi/src/api/IdentityHandler.h index 3824d483d..bac61f574 100644 --- a/libresapi/src/api/IdentityHandler.h +++ b/libresapi/src/api/IdentityHandler.h @@ -32,6 +32,7 @@ private: void handleGetIdentityDetails(Request& req, Response& resp); void handleSetBanNode(Request& req, Response& resp); + void handleSetOpinion(Request& req, Response& resp); ResponseTask *handleOwn(Request& req, Response& resp); ResponseTask *handleCreateIdentity(Request& req, Response& resp); From 1da89dd70d6532d9d661ff630f7caaeca5a84ac0 Mon Sep 17 00:00:00 2001 From: csoler Date: Wed, 19 Apr 2017 17:16:30 +0200 Subject: [PATCH 08/39] changed FFT code in graph widget into a more efficient one, with free licence --- retroshare-gui/src/gui/elastic/fft.h | 827 ++++++++++++++++++ .../src/gui/elastic/graphwidget.cpp | 64 +- 2 files changed, 872 insertions(+), 19 deletions(-) create mode 100644 retroshare-gui/src/gui/elastic/fft.h diff --git a/retroshare-gui/src/gui/elastic/fft.h b/retroshare-gui/src/gui/elastic/fft.h new file mode 100644 index 000000000..12d460c24 --- /dev/null +++ b/retroshare-gui/src/gui/elastic/fft.h @@ -0,0 +1,827 @@ +/****************************************************************** + + Original FFT code Credits: + Copyright Takuya OOURA, 1996-2001 + http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html + +******************************************************************/ + +/* +Fast Fourier/Cosine/Sine Transform + dimension :two + data length :power of 2 + decimation :frequency + radix :4, 2, row-column + data :inplace + table :use +functions + cdft2d: Complex Discrete Fourier Transform + rdft2d: Real Discrete Fourier Transform + ddct2d: Discrete Cosine Transform + ddst2d: Discrete Sine Transform +function prototypes + void cdft2d(int, int, int, double **, int *, double *); + void rdft2d(int, int, int, double **, int *, double *); + void ddct2d(int, int, int, double **, double **, int *, double *); + void ddst2d(int, int, int, double **, double **, int *, double *); + + +-------- Complex DFT (Discrete Fourier Transform) -------- + [definition] + + X[k1][k2] = sum_j1=0^n1-1 sum_j2=0^n2-1 x[j1][j2] * + exp(2*pi*i*j1*k1/n1) * + exp(2*pi*i*j2*k2/n2), 0<=k1 + X[k1][k2] = sum_j1=0^n1-1 sum_j2=0^n2-1 x[j1][j2] * + exp(-2*pi*i*j1*k1/n1) * + exp(-2*pi*i*j2*k2/n2), 0<=k1 + ip[0] = 0; // first time only + cdft2d(n1, 2*n2, 1, a, ip, w); + + ip[0] = 0; // first time only + cdft2d(n1, 2*n2, -1, a, ip, w); + [parameters] + n1 :data length (int) + n1 >= 1, n1 = power of 2 + 2*n2 :data length (int) + n2 >= 1, n2 = power of 2 + a[0...n1-1][0...2*n2-1] + :input/output data (double **) + input data + a[j1][2*j2] = Re(x[j1][j2]), + a[j1][2*j2+1] = Im(x[j1][j2]), + 0<=j1= 2+sqrt(n) + (n = max(n1, n2)) + ip[0],ip[1] are pointers of the cos/sin table. + w[0...*] + :cos/sin table (double *) + length of w >= max(n1/2, n2/2) + w[],ip[] are initialized if ip[0] == 0. + [remark] + Inverse of + cdft2d(n1, 2*n2, -1, a, ip, w); + is + cdft2d(n1, 2*n2, 1, a, ip, w); + for (j1 = 0; j1 <= n1 - 1; j1++) { + for (j2 = 0; j2 <= 2 * n2 - 1; j2++) { + a[j1][j2] *= 1.0 / (n1 * n2); + } + } +*/ + + +/* -------- initializing routines -------- */ + +#pragma once +#include + +class fft +{ +public: + static void makewt(int nw, int *ip, double *w) + { + int nwh, j; + double delta, x, y; + + ip[0] = nw; + ip[1] = 1; + if (nw > 2) { + nwh = nw >> 1; + delta = atan(1.0) / nwh; + w[0] = 1; + w[1] = 0; + w[nwh] = cos(delta * nwh); + w[nwh + 1] = w[nwh]; + for (j = 2; j <= nwh - 2; j += 2) { + sincos(delta*j,&y,&x) ; + //x = cos(delta * j); + //y = sin(delta * j); + w[j] = x; + w[j + 1] = y; + w[nw - j] = y; + w[nw - j + 1] = x; + } + bitrv2(nw, ip + 2, w); + } + } + + + /* -------- child routines -------- */ + + + static void bitrv2(int n, int *ip, double *a) + { + int j, j1, k, k1, l, m, m2; + double xr, xi; + + ip[0] = 0; + l = n; + m = 1; + while ((m << 2) < l) { + l >>= 1; + for (j = 0; j <= m - 1; j++) { + ip[m + j] = ip[j] + l; + } + m <<= 1; + } + if ((m << 2) > l) { + for (k = 1; k <= m - 1; k++) { + for (j = 0; j <= k - 1; j++) { + j1 = (j << 1) + ip[k]; + k1 = (k << 1) + ip[j]; + xr = a[j1]; + xi = a[j1 + 1]; + a[j1] = a[k1]; + a[j1 + 1] = a[k1 + 1]; + a[k1] = xr; + a[k1 + 1] = xi; + } + } + } else { + m2 = m << 1; + for (k = 1; k <= m - 1; k++) { + for (j = 0; j <= k - 1; j++) { + j1 = (j << 1) + ip[k]; + k1 = (k << 1) + ip[j]; + xr = a[j1]; + xi = a[j1 + 1]; + a[j1] = a[k1]; + a[j1 + 1] = a[k1 + 1]; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m2; + k1 += m2; + xr = a[j1]; + xi = a[j1 + 1]; + a[j1] = a[k1]; + a[j1 + 1] = a[k1 + 1]; + a[k1] = xr; + a[k1 + 1] = xi; + } + } + } + } + + + static void bitrv2col(int n1, int n, int *ip, double **a) + { + int i, j, j1, k, k1, l, m, m2; + double xr, xi; + + ip[0] = 0; + l = n; + m = 1; + while ((m << 2) < l) { + l >>= 1; + for (j = 0; j <= m - 1; j++) { + ip[m + j] = ip[j] + l; + } + m <<= 1; + } + if ((m << 2) > l) { + for (i = 0; i <= n1 - 1; i++) { + for (k = 1; k <= m - 1; k++) { + for (j = 0; j <= k - 1; j++) { + j1 = (j << 1) + ip[k]; + k1 = (k << 1) + ip[j]; + xr = a[i][j1]; + xi = a[i][j1 + 1]; + a[i][j1] = a[i][k1]; + a[i][j1 + 1] = a[i][k1 + 1]; + a[i][k1] = xr; + a[i][k1 + 1] = xi; + } + } + } + } else { + m2 = m << 1; + for (i = 0; i <= n1 - 1; i++) { + for (k = 1; k <= m - 1; k++) { + for (j = 0; j <= k - 1; j++) { + j1 = (j << 1) + ip[k]; + k1 = (k << 1) + ip[j]; + xr = a[i][j1]; + xi = a[i][j1 + 1]; + a[i][j1] = a[i][k1]; + a[i][j1 + 1] = a[i][k1 + 1]; + a[i][k1] = xr; + a[i][k1 + 1] = xi; + j1 += m2; + k1 += m2; + xr = a[i][j1]; + xi = a[i][j1 + 1]; + a[i][j1] = a[i][k1]; + a[i][j1 + 1] = a[i][k1 + 1]; + a[i][k1] = xr; + a[i][k1 + 1] = xi; + } + } + } + } + } + + + static void bitrv2row(int n, int n2, int *ip, double **a) + { + int i, j, j1, k, k1, l, m; + double xr, xi; + + ip[0] = 0; + l = n; + m = 1; + while ((m << 1) < l) { + l >>= 1; + for (j = 0; j <= m - 1; j++) { + ip[m + j] = ip[j] + l; + } + m <<= 1; + } + if ((m << 1) > l) { + for (k = 1; k <= m - 1; k++) { + for (j = 0; j <= k - 1; j++) { + j1 = j + ip[k]; + k1 = k + ip[j]; + for (i = 0; i <= n2 - 2; i += 2) { + xr = a[j1][i]; + xi = a[j1][i + 1]; + a[j1][i] = a[k1][i]; + a[j1][i + 1] = a[k1][i + 1]; + a[k1][i] = xr; + a[k1][i + 1] = xi; + } + } + } + } else { + for (k = 1; k <= m - 1; k++) { + for (j = 0; j <= k - 1; j++) { + j1 = j + ip[k]; + k1 = k + ip[j]; + for (i = 0; i <= n2 - 2; i += 2) { + xr = a[j1][i]; + xi = a[j1][i + 1]; + a[j1][i] = a[k1][i]; + a[j1][i + 1] = a[k1][i + 1]; + a[k1][i] = xr; + a[k1][i + 1] = xi; + } + j1 += m; + k1 += m; + for (i = 0; i <= n2 - 2; i += 2) { + xr = a[j1][i]; + xi = a[j1][i + 1]; + a[j1][i] = a[k1][i]; + a[j1][i + 1] = a[k1][i + 1]; + a[k1][i] = xr; + a[k1][i + 1] = xi; + } + } + } + } + } + + + static void cftbcol(int n1, int n, double **a, double *w) + { + int i, j, j1, j2, j3, k, k1, ks, l, m; + double wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; + double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + for (i = 0; i <= n1 - 1; i++) { + l = 2; + while ((l << 1) < n) { + m = l << 2; + for (j = 0; j <= l - 2; j += 2) { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + x0r = a[i][j] + a[i][j1]; + x0i = a[i][j + 1] + a[i][j1 + 1]; + x1r = a[i][j] - a[i][j1]; + x1i = a[i][j + 1] - a[i][j1 + 1]; + x2r = a[i][j2] + a[i][j3]; + x2i = a[i][j2 + 1] + a[i][j3 + 1]; + x3r = a[i][j2] - a[i][j3]; + x3i = a[i][j2 + 1] - a[i][j3 + 1]; + a[i][j] = x0r + x2r; + a[i][j + 1] = x0i + x2i; + a[i][j2] = x0r - x2r; + a[i][j2 + 1] = x0i - x2i; + a[i][j1] = x1r - x3i; + a[i][j1 + 1] = x1i + x3r; + a[i][j3] = x1r + x3i; + a[i][j3 + 1] = x1i - x3r; + } + if (m < n) { + wk1r = w[2]; + for (j = m; j <= l + m - 2; j += 2) { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + x0r = a[i][j] + a[i][j1]; + x0i = a[i][j + 1] + a[i][j1 + 1]; + x1r = a[i][j] - a[i][j1]; + x1i = a[i][j + 1] - a[i][j1 + 1]; + x2r = a[i][j2] + a[i][j3]; + x2i = a[i][j2 + 1] + a[i][j3 + 1]; + x3r = a[i][j2] - a[i][j3]; + x3i = a[i][j2 + 1] - a[i][j3 + 1]; + a[i][j] = x0r + x2r; + a[i][j + 1] = x0i + x2i; + a[i][j2] = x2i - x0i; + a[i][j2 + 1] = x0r - x2r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[i][j1] = wk1r * (x0r - x0i); + a[i][j1 + 1] = wk1r * (x0r + x0i); + x0r = x3i + x1r; + x0i = x3r - x1i; + a[i][j3] = wk1r * (x0i - x0r); + a[i][j3 + 1] = wk1r * (x0i + x0r); + } + k1 = 1; + ks = -1; + for (k = (m << 1); k <= n - m; k += m) { + k1++; + ks = -ks; + wk1r = w[k1 << 1]; + wk1i = w[(k1 << 1) + 1]; + wk2r = ks * w[k1]; + wk2i = w[k1 + ks]; + wk3r = wk1r - 2 * wk2i * wk1i; + wk3i = 2 * wk2i * wk1r - wk1i; + for (j = k; j <= l + k - 2; j += 2) { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + x0r = a[i][j] + a[i][j1]; + x0i = a[i][j + 1] + a[i][j1 + 1]; + x1r = a[i][j] - a[i][j1]; + x1i = a[i][j + 1] - a[i][j1 + 1]; + x2r = a[i][j2] + a[i][j3]; + x2i = a[i][j2 + 1] + a[i][j3 + 1]; + x3r = a[i][j2] - a[i][j3]; + x3i = a[i][j2 + 1] - a[i][j3 + 1]; + a[i][j] = x0r + x2r; + a[i][j + 1] = x0i + x2i; + x0r -= x2r; + x0i -= x2i; + a[i][j2] = wk2r * x0r - wk2i * x0i; + a[i][j2 + 1] = wk2r * x0i + wk2i * x0r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[i][j1] = wk1r * x0r - wk1i * x0i; + a[i][j1 + 1] = wk1r * x0i + wk1i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[i][j3] = wk3r * x0r - wk3i * x0i; + a[i][j3 + 1] = wk3r * x0i + wk3i * x0r; + } + } + } + l = m; + } + if (l < n) { + for (j = 0; j <= l - 2; j += 2) { + j1 = j + l; + x0r = a[i][j] - a[i][j1]; + x0i = a[i][j + 1] - a[i][j1 + 1]; + a[i][j] += a[i][j1]; + a[i][j + 1] += a[i][j1 + 1]; + a[i][j1] = x0r; + a[i][j1 + 1] = x0i; + } + } + } + } + + + static void cftbrow(int n, int n2, double **a, double *w) + { + int i, j, j1, j2, j3, k, k1, ks, l, m; + double wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; + double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + l = 1; + while ((l << 1) < n) { + m = l << 2; + for (j = 0; j <= l - 1; j++) { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + for (i = 0; i <= n2 - 2; i += 2) { + x0r = a[j][i] + a[j1][i]; + x0i = a[j][i + 1] + a[j1][i + 1]; + x1r = a[j][i] - a[j1][i]; + x1i = a[j][i + 1] - a[j1][i + 1]; + x2r = a[j2][i] + a[j3][i]; + x2i = a[j2][i + 1] + a[j3][i + 1]; + x3r = a[j2][i] - a[j3][i]; + x3i = a[j2][i + 1] - a[j3][i + 1]; + a[j][i] = x0r + x2r; + a[j][i + 1] = x0i + x2i; + a[j2][i] = x0r - x2r; + a[j2][i + 1] = x0i - x2i; + a[j1][i] = x1r - x3i; + a[j1][i + 1] = x1i + x3r; + a[j3][i] = x1r + x3i; + a[j3][i + 1] = x1i - x3r; + } + } + if (m < n) { + wk1r = w[2]; + for (j = m; j <= l + m - 1; j++) { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + for (i = 0; i <= n2 - 2; i += 2) { + x0r = a[j][i] + a[j1][i]; + x0i = a[j][i + 1] + a[j1][i + 1]; + x1r = a[j][i] - a[j1][i]; + x1i = a[j][i + 1] - a[j1][i + 1]; + x2r = a[j2][i] + a[j3][i]; + x2i = a[j2][i + 1] + a[j3][i + 1]; + x3r = a[j2][i] - a[j3][i]; + x3i = a[j2][i + 1] - a[j3][i + 1]; + a[j][i] = x0r + x2r; + a[j][i + 1] = x0i + x2i; + a[j2][i] = x2i - x0i; + a[j2][i + 1] = x0r - x2r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j1][i] = wk1r * (x0r - x0i); + a[j1][i + 1] = wk1r * (x0r + x0i); + x0r = x3i + x1r; + x0i = x3r - x1i; + a[j3][i] = wk1r * (x0i - x0r); + a[j3][i + 1] = wk1r * (x0i + x0r); + } + } + k1 = 1; + ks = -1; + for (k = (m << 1); k <= n - m; k += m) { + k1++; + ks = -ks; + wk1r = w[k1 << 1]; + wk1i = w[(k1 << 1) + 1]; + wk2r = ks * w[k1]; + wk2i = w[k1 + ks]; + wk3r = wk1r - 2 * wk2i * wk1i; + wk3i = 2 * wk2i * wk1r - wk1i; + for (j = k; j <= l + k - 1; j++) { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + for (i = 0; i <= n2 - 2; i += 2) { + x0r = a[j][i] + a[j1][i]; + x0i = a[j][i + 1] + a[j1][i + 1]; + x1r = a[j][i] - a[j1][i]; + x1i = a[j][i + 1] - a[j1][i + 1]; + x2r = a[j2][i] + a[j3][i]; + x2i = a[j2][i + 1] + a[j3][i + 1]; + x3r = a[j2][i] - a[j3][i]; + x3i = a[j2][i + 1] - a[j3][i + 1]; + a[j][i] = x0r + x2r; + a[j][i + 1] = x0i + x2i; + x0r -= x2r; + x0i -= x2i; + a[j2][i] = wk2r * x0r - wk2i * x0i; + a[j2][i + 1] = wk2r * x0i + wk2i * x0r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j1][i] = wk1r * x0r - wk1i * x0i; + a[j1][i + 1] = wk1r * x0i + wk1i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3][i] = wk3r * x0r - wk3i * x0i; + a[j3][i + 1] = wk3r * x0i + wk3i * x0r; + } + } + } + } + l = m; + } + if (l < n) { + for (j = 0; j <= l - 1; j++) { + j1 = j + l; + for (i = 0; i <= n2 - 2; i += 2) { + x0r = a[j][i] - a[j1][i]; + x0i = a[j][i + 1] - a[j1][i + 1]; + a[j][i] += a[j1][i]; + a[j][i + 1] += a[j1][i + 1]; + a[j1][i] = x0r; + a[j1][i + 1] = x0i; + } + } + } + } + + + static void cftfcol(int n1, int n, double **a, double *w) + { + int i, j, j1, j2, j3, k, k1, ks, l, m; + double wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; + double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + for (i = 0; i <= n1 - 1; i++) { + l = 2; + while ((l << 1) < n) { + m = l << 2; + for (j = 0; j <= l - 2; j += 2) { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + x0r = a[i][j] + a[i][j1]; + x0i = a[i][j + 1] + a[i][j1 + 1]; + x1r = a[i][j] - a[i][j1]; + x1i = a[i][j + 1] - a[i][j1 + 1]; + x2r = a[i][j2] + a[i][j3]; + x2i = a[i][j2 + 1] + a[i][j3 + 1]; + x3r = a[i][j2] - a[i][j3]; + x3i = a[i][j2 + 1] - a[i][j3 + 1]; + a[i][j] = x0r + x2r; + a[i][j + 1] = x0i + x2i; + a[i][j2] = x0r - x2r; + a[i][j2 + 1] = x0i - x2i; + a[i][j1] = x1r + x3i; + a[i][j1 + 1] = x1i - x3r; + a[i][j3] = x1r - x3i; + a[i][j3 + 1] = x1i + x3r; + } + if (m < n) { + wk1r = w[2]; + for (j = m; j <= l + m - 2; j += 2) { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + x0r = a[i][j] + a[i][j1]; + x0i = a[i][j + 1] + a[i][j1 + 1]; + x1r = a[i][j] - a[i][j1]; + x1i = a[i][j + 1] - a[i][j1 + 1]; + x2r = a[i][j2] + a[i][j3]; + x2i = a[i][j2 + 1] + a[i][j3 + 1]; + x3r = a[i][j2] - a[i][j3]; + x3i = a[i][j2 + 1] - a[i][j3 + 1]; + a[i][j] = x0r + x2r; + a[i][j + 1] = x0i + x2i; + a[i][j2] = x0i - x2i; + a[i][j2 + 1] = x2r - x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[i][j1] = wk1r * (x0i + x0r); + a[i][j1 + 1] = wk1r * (x0i - x0r); + x0r = x3i - x1r; + x0i = x3r + x1i; + a[i][j3] = wk1r * (x0r + x0i); + a[i][j3 + 1] = wk1r * (x0r - x0i); + } + k1 = 1; + ks = -1; + for (k = (m << 1); k <= n - m; k += m) { + k1++; + ks = -ks; + wk1r = w[k1 << 1]; + wk1i = w[(k1 << 1) + 1]; + wk2r = ks * w[k1]; + wk2i = w[k1 + ks]; + wk3r = wk1r - 2 * wk2i * wk1i; + wk3i = 2 * wk2i * wk1r - wk1i; + for (j = k; j <= l + k - 2; j += 2) { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + x0r = a[i][j] + a[i][j1]; + x0i = a[i][j + 1] + a[i][j1 + 1]; + x1r = a[i][j] - a[i][j1]; + x1i = a[i][j + 1] - a[i][j1 + 1]; + x2r = a[i][j2] + a[i][j3]; + x2i = a[i][j2 + 1] + a[i][j3 + 1]; + x3r = a[i][j2] - a[i][j3]; + x3i = a[i][j2 + 1] - a[i][j3 + 1]; + a[i][j] = x0r + x2r; + a[i][j + 1] = x0i + x2i; + x0r -= x2r; + x0i -= x2i; + a[i][j2] = wk2r * x0r + wk2i * x0i; + a[i][j2 + 1] = wk2r * x0i - wk2i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[i][j1] = wk1r * x0r + wk1i * x0i; + a[i][j1 + 1] = wk1r * x0i - wk1i * x0r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[i][j3] = wk3r * x0r + wk3i * x0i; + a[i][j3 + 1] = wk3r * x0i - wk3i * x0r; + } + } + } + l = m; + } + if (l < n) { + for (j = 0; j <= l - 2; j += 2) { + j1 = j + l; + x0r = a[i][j] - a[i][j1]; + x0i = a[i][j + 1] - a[i][j1 + 1]; + a[i][j] += a[i][j1]; + a[i][j + 1] += a[i][j1 + 1]; + a[i][j1] = x0r; + a[i][j1 + 1] = x0i; + } + } + } + } + + + static void cftfrow(int n, int n2, double **a, double *w) + { + int i, j, j1, j2, j3, k, k1, ks, l, m; + double wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; + double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + l = 1; + while ((l << 1) < n) { + m = l << 2; + for (j = 0; j <= l - 1; j++) { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + for (i = 0; i <= n2 - 2; i += 2) { + x0r = a[j][i] + a[j1][i]; + x0i = a[j][i + 1] + a[j1][i + 1]; + x1r = a[j][i] - a[j1][i]; + x1i = a[j][i + 1] - a[j1][i + 1]; + x2r = a[j2][i] + a[j3][i]; + x2i = a[j2][i + 1] + a[j3][i + 1]; + x3r = a[j2][i] - a[j3][i]; + x3i = a[j2][i + 1] - a[j3][i + 1]; + a[j][i] = x0r + x2r; + a[j][i + 1] = x0i + x2i; + a[j2][i] = x0r - x2r; + a[j2][i + 1] = x0i - x2i; + a[j1][i] = x1r + x3i; + a[j1][i + 1] = x1i - x3r; + a[j3][i] = x1r - x3i; + a[j3][i + 1] = x1i + x3r; + } + } + if (m < n) { + wk1r = w[2]; + for (j = m; j <= l + m - 1; j++) { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + for (i = 0; i <= n2 - 2; i += 2) { + x0r = a[j][i] + a[j1][i]; + x0i = a[j][i + 1] + a[j1][i + 1]; + x1r = a[j][i] - a[j1][i]; + x1i = a[j][i + 1] - a[j1][i + 1]; + x2r = a[j2][i] + a[j3][i]; + x2i = a[j2][i + 1] + a[j3][i + 1]; + x3r = a[j2][i] - a[j3][i]; + x3i = a[j2][i + 1] - a[j3][i + 1]; + a[j][i] = x0r + x2r; + a[j][i + 1] = x0i + x2i; + a[j2][i] = x0i - x2i; + a[j2][i + 1] = x2r - x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j1][i] = wk1r * (x0i + x0r); + a[j1][i + 1] = wk1r * (x0i - x0r); + x0r = x3i - x1r; + x0i = x3r + x1i; + a[j3][i] = wk1r * (x0r + x0i); + a[j3][i + 1] = wk1r * (x0r - x0i); + } + } + k1 = 1; + ks = -1; + for (k = (m << 1); k <= n - m; k += m) { + k1++; + ks = -ks; + wk1r = w[k1 << 1]; + wk1i = w[(k1 << 1) + 1]; + wk2r = ks * w[k1]; + wk2i = w[k1 + ks]; + wk3r = wk1r - 2 * wk2i * wk1i; + wk3i = 2 * wk2i * wk1r - wk1i; + for (j = k; j <= l + k - 1; j++) { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + for (i = 0; i <= n2 - 2; i += 2) { + x0r = a[j][i] + a[j1][i]; + x0i = a[j][i + 1] + a[j1][i + 1]; + x1r = a[j][i] - a[j1][i]; + x1i = a[j][i + 1] - a[j1][i + 1]; + x2r = a[j2][i] + a[j3][i]; + x2i = a[j2][i + 1] + a[j3][i + 1]; + x3r = a[j2][i] - a[j3][i]; + x3i = a[j2][i + 1] - a[j3][i + 1]; + a[j][i] = x0r + x2r; + a[j][i + 1] = x0i + x2i; + x0r -= x2r; + x0i -= x2i; + a[j2][i] = wk2r * x0r + wk2i * x0i; + a[j2][i + 1] = wk2r * x0i - wk2i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j1][i] = wk1r * x0r + wk1i * x0i; + a[j1][i + 1] = wk1r * x0i - wk1i * x0r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j3][i] = wk3r * x0r + wk3i * x0i; + a[j3][i + 1] = wk3r * x0i - wk3i * x0r; + } + } + } + } + l = m; + } + if (l < n) { + for (j = 0; j <= l - 1; j++) { + j1 = j + l; + for (i = 0; i <= n2 - 2; i += 2) { + x0r = a[j][i] - a[j1][i]; + x0i = a[j][i + 1] - a[j1][i + 1]; + a[j][i] += a[j1][i]; + a[j][i + 1] += a[j1][i + 1]; + a[j1][i] = x0r; + a[j1][i + 1] = x0i; + } + } + } + } + static int *alloc_1d_int(int n1) + { + int *i; + + i = (int *) malloc(sizeof(int) * n1); + return i; + } + + static void free_1d_int(int *i) { free(i); } + + static double *alloc_1d_double(int n1) + { + double *d; + + d = (double *) malloc(sizeof(double) * n1); + return d; + } + + + static void free_1d_double(double *d) { free(d); } + static double **alloc_2d_double(int n1, int n2) + { + double **dd, *d; + int j; + + dd = (double **) malloc(sizeof(double *) * n1); + d = (double *) malloc(sizeof(double) * n1 * n2); + + dd[0] = d; + for (j = 1; j < n1; j++) { + dd[j] = dd[j - 1] + n2; + } + return dd; + } + + static void free_2d_double(double **dd) { free(dd[0]); free(dd); } + + + static void cdft2d(int n1, int n2, int isgn, double **a, int *ip, double *w) + { + int n; + + n = n1 << 1; + if (n < n2) { + n = n2; + } + if (n > (ip[0] << 2)) { + makewt(n >> 2, ip, w); + } + if (n2 > 4) { + bitrv2col(n1, n2, ip + 2, a); + } + if (n1 > 2) { + bitrv2row(n1, n2, ip + 2, a); + } + if (isgn < 0) { + cftfcol(n1, n2, a, w); + cftfrow(n1, n2, a, w); + } else { + cftbcol(n1, n2, a, w); + cftbrow(n1, n2, a, w); + } + } +}; diff --git a/retroshare-gui/src/gui/elastic/graphwidget.cpp b/retroshare-gui/src/gui/elastic/graphwidget.cpp index a2c69c80d..099ca3d7d 100644 --- a/retroshare-gui/src/gui/elastic/graphwidget.cpp +++ b/retroshare-gui/src/gui/elastic/graphwidget.cpp @@ -42,6 +42,7 @@ #include "graphwidget.h" #include "edge.h" #include "node.h" +#include "fft.h" #include #include @@ -259,45 +260,70 @@ void GraphWidget::keyPressEvent(QKeyEvent *event) } } -static void convolveWithGaussian(double *forceMap,unsigned int S,int /*s*/) +static void convolveWithForce(double *forceMap,unsigned int S,int /*s*/) { - static double *bf = NULL ; + static double **bf = NULL ; + static double **tmp = NULL ; + static int *ip = NULL ; + static double *w = NULL ; + static uint32_t last_S = 0 ; if(bf == NULL) { - bf = new double[S*S*2] ; + bf = fft::alloc_2d_double(S, 2*S); for(unsigned int i=0;i derivative is constant - bf[2*(i+S*j)+1] = 0 ; + + bf[i][j*2+0] = log(sqrtf(0.1 + x*x+y*y)); // linear -> derivative is constant + bf[i][j*2+1] = 0 ; } - unsigned long nn[2] = {S,S}; - fourn(&bf[-1],&nn[-1],2,1) ; + //unsigned long nn[2] = {S,S}; + //fourn(&bf[-1],&nn[-1],2,1) ; + + ip = fft::alloc_1d_int(2 + (int) sqrt(S + 0.5)); + w = fft::alloc_1d_double(S/2+S); + ip[0] = 0; + + fft::cdft2d(S, 2*S, 1, bf, ip, w); } - unsigned long nn[2] = {S,S}; - fourn(&forceMap[-1],&nn[-1],2,1) ; + if(last_S != S) + { + if(tmp) + fft::free_2d_double(tmp) ; + + tmp = fft::alloc_2d_double(S, 2*S); + last_S = S ; + } + memcpy(tmp[0],forceMap,S*S*2*sizeof(double)) ; + + fft::cdft2d(S, 2*S, 1, tmp, ip, w); + + //fourn(&forceMap[-1],&nn[-1],2,1) ; for (unsigned int i=0;isceneRect()) ; - if( (hit++ & 7) == 0) + if( (hit++ & 3) == 0) { memset(forceMap,0,2*S*S*sizeof(double)) ; @@ -348,7 +374,7 @@ void GraphWidget::timerEvent(QTimerEvent *event) } // compute convolution with 1/omega kernel. - convolveWithGaussian(forceMap,S,20) ; + convolveWithForce(forceMap,S,20) ; } foreach (Node *node, _nodes) From f406b8123867240479ea35dee168c58957f51cbb Mon Sep 17 00:00:00 2001 From: csoler Date: Wed, 19 Apr 2017 18:46:58 +0200 Subject: [PATCH 09/39] removed all FFT code and cleaned up deleted code in graphwidget.cpp --- .../src/gui/elastic/graphwidget.cpp | 145 ------------------ 1 file changed, 145 deletions(-) diff --git a/retroshare-gui/src/gui/elastic/graphwidget.cpp b/retroshare-gui/src/gui/elastic/graphwidget.cpp index 099ca3d7d..9aeebbeda 100644 --- a/retroshare-gui/src/gui/elastic/graphwidget.cpp +++ b/retroshare-gui/src/gui/elastic/graphwidget.cpp @@ -51,86 +51,9 @@ #include -#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr - -void fourn(double data[],unsigned long nn[],unsigned long ndim,int isign) -{ - int i1,i2,i3,i2rev,i3rev,ip1,ip2,ip3,ifp1,ifp2; - int ibit,idim,k1,k2,n,nprev,nrem,ntot; - double tempi,tempr; - double theta,wi,wpi,wpr,wr,wtemp; - - ntot=1; - for (idim=1;idim<=(long)ndim;++idim) - ntot *= nn[idim]; - nprev=1; - for (idim=ndim;idim>=1;idim--) { - n=nn[idim]; - nrem=ntot/(n*nprev); - ip1=nprev << 1; - ip2=ip1*n; - ip3=ip2*nrem; - i2rev=1; - for (i2=1;i2<=ip2;i2+=ip1) { - if (i2 < i2rev) { - for (i1=i2;i1<=i2+ip1-2;i1+=2) { - for (i3=i1;i3<=ip3;i3+=ip2) { - i3rev=i2rev+i3-i2; - SWAP(data[i3],data[i3rev]); - SWAP(data[i3+1],data[i3rev+1]); - } - } - } - ibit=ip2 >> 1; - while (ibit >= ip1 && i2rev > ibit) { - i2rev -= ibit; - ibit >>= 1; - } - i2rev += ibit; - } - ifp1=ip1; - while (ifp1 < ip2) { - ifp2=ifp1 << 1; - theta=isign*6.28318530717959/(ifp2/ip1); - wtemp=sin(0.5*theta); - wpr = -2.0*wtemp*wtemp; - wpi=sin(theta); - wr=1.0; - wi=0.0; - for (i3=1;i3<=ifp1;i3+=ip1) { - for (i1=i3;i1<=i3+ip1-2;i1+=2) { - for (i2=i1;i2<=ip3;i2+=ifp2) { - k1=i2; - k2=k1+ifp1; - tempr=wr*data[k2]-wi*data[k2+1]; - tempi=wr*data[k2+1]+wi*data[k2]; - data[k2]=data[k1]-tempr; - data[k2+1]=data[k1+1]-tempi; - data[k1] += tempr; - data[k1+1] += tempi; - } - } - wr=(wtemp=wr)*wpr-wi*wpi+wr; - wi=wi*wpr+wtemp*wpi+wi; - } - ifp1=ifp2; - } - nprev *= n; - } -} - -#undef SWAP - GraphWidget::GraphWidget(QWidget *) : timerId(0), mIsFrozen(false) { -// QGraphicsScene *scene = new QGraphicsScene(QRectF(0,0,500,500),this); -// scene->setItemIndexMethod(QGraphicsScene::NoIndex); -// scene->clear() ; -// setScene(scene); - -// scene()->setSceneRect(0, 0, width(), height()); - setCacheMode(CacheBackground); setViewportUpdateMode(BoundingRectViewportUpdate); setRenderHint(QPainter::Antialiasing); @@ -143,18 +66,6 @@ GraphWidget::GraphWidget(QWidget *) void GraphWidget::clearGraph() { -// QGraphicsScene *scene = new QGraphicsScene(this); -// scene->setItemIndexMethod(QGraphicsScene::NoIndex); -// setScene(scene); - -// scene->addItem(centerNode); -// centerNode->setPos(0, 0); - -// if (oldscene != NULL) -// { -// delete oldscene; -// } - scene()->clear(); scene()->setSceneRect(0, 0, width(), height()); @@ -230,18 +141,6 @@ void GraphWidget::itemMoved() void GraphWidget::keyPressEvent(QKeyEvent *event) { switch (event->key()) { -// case Qt::Key_Up: -// centerNode->moveBy(0, -20); -// break; -// case Qt::Key_Down: -// centerNode->moveBy(0, 20); -// break; -// case Qt::Key_Left: -// centerNode->moveBy(-20, 0); -// break; -// case Qt::Key_Right: -// centerNode->moveBy(20, 0); -// break; case Qt::Key_Plus: scaleView(qreal(1.2)); break; @@ -282,9 +181,6 @@ static void convolveWithForce(double *forceMap,unsigned int S,int /*s*/) bf[i][j*2+1] = 0 ; } - //unsigned long nn[2] = {S,S}; - //fourn(&bf[-1],&nn[-1],2,1) ; - ip = fft::alloc_1d_int(2 + (int) sqrt(S + 0.5)); w = fft::alloc_1d_double(S/2+S); ip[0] = 0; @@ -304,8 +200,6 @@ static void convolveWithForce(double *forceMap,unsigned int S,int /*s*/) fft::cdft2d(S, 2*S, 1, tmp, ip, w); - //fourn(&forceMap[-1],&nn[-1],2,1) ; - for (unsigned int i=0;idelta() / 240.0)); } -//void GraphWidget::drawBackground(QPainter *painter, const QRectF &rect) -//{ -// Q_UNUSED(rect); -// -// // Shadow -// QRectF sceneRect = this->sceneRect(); -// QRectF rightShadow(sceneRect.right(), sceneRect.top() + 5, 5, sceneRect.height()); -// QRectF bottomShadow(sceneRect.left() + 5, sceneRect.bottom(), sceneRect.width(), 5); -// if (rightShadow.intersects(rect) || rightShadow.contains(rect)) -// painter->fillRect(rightShadow, Qt::darkGray); -// if (bottomShadow.intersects(rect) || bottomShadow.contains(rect)) -// painter->fillRect(bottomShadow, Qt::darkGray); -// -// // Fill -// QLinearGradient gradient(sceneRect.topLeft(), sceneRect.bottomRight()); -// gradient.setColorAt(0, Qt::white); -// gradient.setColorAt(1, Qt::lightGray); -// painter->fillRect(rect.intersected(sceneRect), gradient); -// painter->setBrush(Qt::NoBrush); -// painter->drawRect(sceneRect); -// -// // Text -// QRectF textRect(sceneRect.left() + 4, sceneRect.top() + 4, -// sceneRect.width() - 4, sceneRect.height() - 4); -// QString message(tr("Click and drag the nodes around, and zoom with the mouse " -// "wheel or the '+' and '-' keys")); -// -// QFont font = painter->font(); -// font.setBold(true); -// font.setPointSize(14); -// painter->setFont(font); -// painter->setPen(Qt::lightGray); -// painter->drawText(textRect.translated(2, 2), message); -// painter->setPen(Qt::black); -// painter->drawText(textRect, message); -//} - void GraphWidget::scaleView(qreal scaleFactor) { qreal factor = matrix().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width(); From 4a0b51ce2d853c3466940f19f642854225e238d2 Mon Sep 17 00:00:00 2001 From: Konrad Date: Wed, 19 Apr 2017 22:03:24 +0200 Subject: [PATCH 10/39] Added: to response information whether the identity is a contact --- libresapi/src/api/IdentityHandler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libresapi/src/api/IdentityHandler.cpp b/libresapi/src/api/IdentityHandler.cpp index 420d310a5..67e5cb4c6 100644 --- a/libresapi/src/api/IdentityHandler.cpp +++ b/libresapi/src/api/IdentityHandler.cpp @@ -207,6 +207,7 @@ void IdentityHandler::handleWildcard(Request & /*req*/, Response &resp) << makeKeyValueReference("gxs_id", grp.mMeta.mGroupId) << makeKeyValueReference("pgp_id",grp.mPgpId ) << makeKeyValueReference("name", grp.mMeta.mGroupName) + << makeKeyValueReference("contact", grp.mIsAContact) << makeKeyValueReference("own", own) << makeKeyValueReference("pgp_linked", pgp_linked); } From 9600359bdb62cc05e553f846dbf243bde5830f37 Mon Sep 17 00:00:00 2001 From: Konrad Date: Thu, 20 Apr 2017 18:09:19 +0200 Subject: [PATCH 11/39] Fixed: Password was not stored after creating a new location --- libresapi/src/api/RsControlModule.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libresapi/src/api/RsControlModule.cpp b/libresapi/src/api/RsControlModule.cpp index 2910bc443..cb3cdcdf2 100644 --- a/libresapi/src/api/RsControlModule.cpp +++ b/libresapi/src/api/RsControlModule.cpp @@ -456,6 +456,7 @@ void RsControlModule::handleCreateLocation(Request &req, Response &resp) // give the password to the password callback { RsStackMutex stack(mDataMtx); // ********** LOCKED ********** + mPassword = pgp_password; mFixedPassword = pgp_password; } bool ssl_ok = RsAccounts::GenerateSSLCertificate(pgp_id, "", ssl_name, "", hidden_port!=0, ssl_password, ssl_id, err_string); From c9f618ddf602f1623fcb3a99741bde3015476b10 Mon Sep 17 00:00:00 2001 From: Konrad Date: Thu, 20 Apr 2017 19:09:57 +0200 Subject: [PATCH 12/39] Added: Notification about changed peer status --- libresapi/src/api/PeersHandler.cpp | 6 ++++++ libresapi/src/api/PeersHandler.h | 1 + 2 files changed, 7 insertions(+) diff --git a/libresapi/src/api/PeersHandler.cpp b/libresapi/src/api/PeersHandler.cpp index 3ba827a33..6649acdcb 100644 --- a/libresapi/src/api/PeersHandler.cpp +++ b/libresapi/src/api/PeersHandler.cpp @@ -221,6 +221,12 @@ void PeersHandler::notifyListChange(int list, int /* type */) } } +void PeersHandler::notifyPeerStatusChanged(const std::string& /*peer_id*/, uint32_t /*state*/) +{ + RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ + mStateTokenServer->replaceToken(mStateToken); +} + void PeersHandler::notifyPeerHasNewAvatar(std::string /*peer_id*/) { RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ diff --git a/libresapi/src/api/PeersHandler.h b/libresapi/src/api/PeersHandler.h index a7386d8c9..c4e0ddc3d 100644 --- a/libresapi/src/api/PeersHandler.h +++ b/libresapi/src/api/PeersHandler.h @@ -21,6 +21,7 @@ public: // from NotifyClient // note: this may get called from foreign threads virtual void notifyListChange(int list, int type); // friends list change + virtual void notifyPeerStatusChanged(const std::string& /*peer_id*/, uint32_t /*state*/); virtual void notifyPeerHasNewAvatar(std::string /*peer_id*/); // from Tickable From 5f8bf03dfea7570473cd8960b91e1db82bd12eaa Mon Sep 17 00:00:00 2001 From: csoler Date: Thu, 20 Apr 2017 20:54:51 +0200 Subject: [PATCH 13/39] added mechanism to allow services to document the names of their items, and improved bandwidth graph to show names for GXS services. Other services still need to supply their own names --- libretroshare/src/gxs/rsgxsnetservice.cc | 17 +++++ libretroshare/src/gxs/rsgxsnetservice.h | 1 + libretroshare/src/pqi/p3servicecontrol.cc | 67 +++++++++++-------- libretroshare/src/pqi/p3servicecontrol.h | 8 +++ libretroshare/src/pqi/pqiservice.cc | 17 ++++- libretroshare/src/pqi/pqiservice.h | 44 ++++++------ .../src/retroshare/rsservicecontrol.h | 1 + libretroshare/src/rsserver/rsinit.cc | 2 + .../src/gui/common/RSGraphWidget.cpp | 52 +++++++++++--- retroshare-gui/src/gui/common/RSGraphWidget.h | 12 +++- retroshare-gui/src/gui/statistics/BWGraph.cpp | 62 ++++++++++++++--- retroshare-gui/src/gui/statistics/BWGraph.h | 13 +++- .../gui/statistics/BandwidthStatsWidget.cpp | 28 ++++++-- .../src/gui/statistics/BandwidthStatsWidget.h | 3 +- .../gui/statistics/BandwidthStatsWidget.ui | 34 +++++++++- 15 files changed, 280 insertions(+), 81 deletions(-) diff --git a/libretroshare/src/gxs/rsgxsnetservice.cc b/libretroshare/src/gxs/rsgxsnetservice.cc index 3811ddd0c..7258ae775 100644 --- a/libretroshare/src/gxs/rsgxsnetservice.cc +++ b/libretroshare/src/gxs/rsgxsnetservice.cc @@ -328,6 +328,23 @@ RsGxsNetService::RsGxsNetService(uint16_t servType, RsGeneralDataService *gds, mUpdateCounter = 0; } +void RsGxsNetService::getItemNames(std::map& names) const +{ + names.clear(); + + names[RS_PKT_SUBTYPE_NXS_SYNC_GRP_REQ_ITEM ] = "Group Sync Request" ; + names[RS_PKT_SUBTYPE_NXS_SYNC_GRP_ITEM ] = "Group Sync" ; + names[RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS_ITEM ] = "Group Stats" ; + names[RS_PKT_SUBTYPE_NXS_GRP_ITEM ] = "Group Data" ; + names[RS_PKT_SUBTYPE_NXS_ENCRYPTED_DATA_ITEM ] = "Encrypted data" ; + names[RS_PKT_SUBTYPE_NXS_SESSION_KEY_ITEM ] = "Session Key" ; + names[RS_PKT_SUBTYPE_NXS_SYNC_MSG_ITEM ] = "Message Sync" ; + names[RS_PKT_SUBTYPE_NXS_SYNC_MSG_REQ_ITEM ] = "Message Sync Request" ; + names[RS_PKT_SUBTYPE_NXS_MSG_ITEM ] = "Message Data" ; + names[RS_PKT_SUBTYPE_NXS_TRANSAC_ITEM ] = "Transaction" ; + names[RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY_ITEM ] = "Publish key" ; +} + RsGxsNetService::~RsGxsNetService() { RS_STACK_MUTEX(mNxsMutex) ; diff --git a/libretroshare/src/gxs/rsgxsnetservice.h b/libretroshare/src/gxs/rsgxsnetservice.h index b14d55058..fba79ebc9 100644 --- a/libretroshare/src/gxs/rsgxsnetservice.h +++ b/libretroshare/src/gxs/rsgxsnetservice.h @@ -99,6 +99,7 @@ public: virtual RsServiceInfo getServiceInfo() { return mServiceInfo; } + virtual void getItemNames(std::map& names) const ; public: diff --git a/libretroshare/src/pqi/p3servicecontrol.cc b/libretroshare/src/pqi/p3servicecontrol.cc index a397a4e1c..799093d29 100644 --- a/libretroshare/src/pqi/p3servicecontrol.cc +++ b/libretroshare/src/pqi/p3servicecontrol.cc @@ -29,7 +29,9 @@ #include "serialiser/rsserviceids.h" #include "serialiser/rsserial.h" #include "serialiser/rsbaseserial.h" +#include "serialiser/rsnxsitems.h" #include "pqi/p3cfgmgr.h" +#include "pqi/pqiservice.h" /*******************************/ // #define SERVICECONTROL_DEBUG 1 @@ -138,7 +140,7 @@ public: std::cerr << __PRETTY_FUNCTION__ << ": error while deserialising! Item will be dropped." << std::endl; return NULL ; } - + /* add mandatory parts first */ ok &= getRawUInt32(data, rssize, &offset, &item->mServiceId); ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_NAME, item->mServiceName); @@ -248,6 +250,13 @@ const RsPeerId& p3ServiceControl::getOwnId() return mOwnPeerId; } +bool p3ServiceControl::getServiceItemNames(uint32_t serviceId,std::map& names) +{ + if(mServiceServer != NULL) + return mServiceServer->getServiceItemNames(serviceId,names) ; + + return false ; +} /* Interface for Services */ bool p3ServiceControl::registerService(const RsServiceInfo &info, bool defaultOn) @@ -537,7 +546,7 @@ bool p3ServiceControl::updateServicePermissions(uint32_t serviceId, const RsServ { for(pit = onlinePeers.begin(); pit != onlinePeers.end(); ++pit) { - if (it->second.peerHasPermission(*pit) != + if (it->second.peerHasPermission(*pit) != permissions.peerHasPermission(*pit)) { mUpdatedSet.insert(*pit); @@ -597,7 +606,7 @@ bool p3ServiceControl::checkFilter(uint32_t serviceId, const RsPeerId &peerId) #endif // must allow ServiceInfo through, or we have nothing! -#define FULLID_SERVICEINFO ((((uint32_t) RS_PKT_VERSION_SERVICE) << 24) + ((RS_SERVICE_TYPE_SERVICEINFO) << 8)) +#define FULLID_SERVICEINFO ((((uint32_t) RS_PKT_VERSION_SERVICE) << 24) + ((RS_SERVICE_TYPE_SERVICEINFO) << 8)) //if (serviceId == RS_SERVICE_TYPE_SERVICEINFO) if (serviceId == FULLID_SERVICEINFO) @@ -691,21 +700,21 @@ bool ServiceInfoCompatible(const RsServiceInfo &info1, const RsServiceInfo &info } // ensure that info1 meets minimum requirements for info2 - if (!versionOkay(info1.mVersionMajor, info1.mVersionMinor, + if (!versionOkay(info1.mVersionMajor, info1.mVersionMinor, info2.mMinVersionMajor, info2.mMinVersionMinor)) { return false; } // ensure that info2 meets minimum requirements for info1 - if (!versionOkay(info2.mVersionMajor, info2.mVersionMinor, + if (!versionOkay(info2.mVersionMajor, info2.mVersionMinor, info1.mMinVersionMajor, info1.mMinVersionMinor)) { return false; } return true; } - + bool p3ServiceControl::updateFilterByPeer(const RsPeerId &peerId) { @@ -790,8 +799,8 @@ bool p3ServiceControl::updateFilterByPeer_locked(const RsPeerId &peerId) std::cerr << "p3ServiceControl::updateFilterByPeer_locked() Empty ... Clearing"; std::cerr << std::endl; #endif - - // empty, remove... + + // empty, remove... recordFilterChanges_locked(peerId, originalFilter, peerFilter); if (fit != mPeerFilterMap.end()) { @@ -882,7 +891,7 @@ bool p3ServiceControl::updateFilterByPeer_locked(const RsPeerId &peerId) std::cerr << "p3ServiceControl::updateFilterByPeer_locked() Empty(2) ... Clearing"; std::cerr << std::endl; #endif - + if (fit != mPeerFilterMap.end()) { mPeerFilterMap.erase(fit); @@ -900,7 +909,7 @@ bool p3ServiceControl::updateFilterByPeer_locked(const RsPeerId &peerId) return true; } -void p3ServiceControl::recordFilterChanges_locked(const RsPeerId &peerId, +void p3ServiceControl::recordFilterChanges_locked(const RsPeerId &peerId, ServicePeerFilter &originalFilter, ServicePeerFilter &updatedFilter) { #ifdef SERVICECONTROL_DEBUG @@ -1202,7 +1211,7 @@ bool p3ServiceControl::loadList(std::list& loadList) if(item != NULL) mServicePermissionMap[item->mServiceId] = *item ; - + delete *it ; } @@ -1396,49 +1405,49 @@ void p3ServiceControl::notifyServices() std::cerr << "p3ServiceControl::notifyServices(): Noone Monitoring ... skipping"; std::cerr << std::endl; #endif - + continue; } - + std::list peers; std::set::const_iterator pit; - for(pit = it->second.mAdded.begin(); + for(pit = it->second.mAdded.begin(); pit != it->second.mAdded.end(); ++pit) { pqiServicePeer peer; peer.id = *pit; peer.actions = RS_SERVICE_PEER_CONNECTED; - + peers.push_back(peer); - + #ifdef SERVICECONTROL_DEBUG std::cerr << "p3ServiceControl::notifyServices(): Peer: " << *pit << " CONNECTED"; std::cerr << std::endl; #endif } - - for(pit = it->second.mRemoved.begin(); + + for(pit = it->second.mRemoved.begin(); pit != it->second.mRemoved.end(); ++pit) { pqiServicePeer peer; peer.id = *pit; peer.actions = RS_SERVICE_PEER_DISCONNECTED; - + peers.push_back(peer); - + #ifdef SERVICECONTROL_DEBUG std::cerr << "p3ServiceControl::notifyServices(): Peer: " << *pit << " DISCONNECTED"; std::cerr << std::endl; #endif } - + for(; sit != eit; ++sit) { #ifdef SERVICECONTROL_DEBUG std::cerr << "p3ServiceControl::notifyServices(): Sending to Monitoring Service"; std::cerr << std::endl; #endif - + sit->second->statusChange(peers); } } @@ -1500,17 +1509,17 @@ void RsServicePermissions::resetPermission(const RsPeerId& peerId) } RsServiceInfo::RsServiceInfo( - const uint16_t service_type, - const std::string service_name, + const uint16_t service_type, + const std::string service_name, const uint16_t version_major, const uint16_t version_minor, const uint16_t min_version_major, const uint16_t min_version_minor) - :mServiceName(service_name), - mServiceType((((uint32_t) RS_PKT_VERSION_SERVICE) << 24) + (((uint32_t) service_type) << 8)), - mVersionMajor(version_major), + :mServiceName(service_name), + mServiceType((((uint32_t) RS_PKT_VERSION_SERVICE) << 24) + (((uint32_t) service_type) << 8)), + mVersionMajor(version_major), mVersionMinor(version_minor), - mMinVersionMajor(min_version_major), + mMinVersionMajor(min_version_major), mMinVersionMinor(min_version_minor) { return; @@ -1518,7 +1527,7 @@ RsServiceInfo::RsServiceInfo( RsServiceInfo::RsServiceInfo() - :mServiceName("unknown"), + :mServiceName("unknown"), mServiceType(0), mVersionMajor(0), mVersionMinor(0), diff --git a/libretroshare/src/pqi/p3servicecontrol.h b/libretroshare/src/pqi/p3servicecontrol.h index 948481a2b..9c9724347 100644 --- a/libretroshare/src/pqi/p3servicecontrol.h +++ b/libretroshare/src/pqi/p3servicecontrol.h @@ -36,6 +36,8 @@ #include "pqi/pqiservicemonitor.h" #include "pqi/p3linkmgr.h" +class p3ServiceServer ; + class ServiceNotifications { public: @@ -101,6 +103,9 @@ virtual bool updateServicePermissions(uint32_t serviceId, const RsServicePermiss virtual void getPeersConnected(const uint32_t serviceId, std::set &peerSet); virtual bool isPeerConnected(const uint32_t serviceId, const RsPeerId &peerId); + // Gets the list of items used by that service +virtual bool getServiceItemNames(uint32_t serviceId,std::map& names) ; + /** * Registration for all Services. */ @@ -132,6 +137,8 @@ virtual bool updateServicesProvided(const RsPeerId &peerId, const RsPeerServiceI // pqiMonitor. virtual void statusChange(const std::list &plist); + virtual void setServiceServer(p3ServiceServer *p) { mServiceServer = p ; } + protected: // configuration. virtual bool saveList(bool &cleanup, std::list&); @@ -196,6 +203,7 @@ bool peerHasPermissionForService_locked(const RsPeerId &peerId, uint32_t service // Below here is saved in Configuration. std::map mServicePermissionMap; + p3ServiceServer *mServiceServer ; }; diff --git a/libretroshare/src/pqi/pqiservice.cc b/libretroshare/src/pqi/pqiservice.cc index 4ba249c69..d9c93cc18 100644 --- a/libretroshare/src/pqi/pqiservice.cc +++ b/libretroshare/src/pqi/pqiservice.cc @@ -79,11 +79,26 @@ int p3ServiceServer::addService(pqiService *ts, bool defaultOn) services[info.mServiceType] = ts; // This doesn't need to be in Mutex. - mServiceControl->registerService(info, defaultOn); + mServiceControl->registerService(info,defaultOn); return 1; } +bool p3ServiceServer::getServiceItemNames(uint32_t service_type,std::map& names) +{ + RsStackMutex stack(srvMtx); /********* LOCKED *********/ + + std::map::iterator it=services.find(service_type) ; + + if(it != services.end()) + { + it->second->getItemNames(names) ; + return true ; + } + else + return false ; +} + int p3ServiceServer::removeService(pqiService *ts) { RsStackMutex stack(srvMtx); /********* LOCKED *********/ diff --git a/libretroshare/src/pqi/pqiservice.h b/libretroshare/src/pqi/pqiservice.h index c293cc005..b22a34aac 100644 --- a/libretroshare/src/pqi/pqiservice.h +++ b/libretroshare/src/pqi/pqiservice.h @@ -60,24 +60,26 @@ class p3ServiceServerIface; class pqiService { - protected: +protected: pqiService() // our type of packets. - :mServiceServer(NULL) { return; } + :mServiceServer(NULL) { return; } -virtual ~pqiService() { return; } + virtual ~pqiService() { return; } - public: -void setServiceServer(p3ServiceServerIface *server); - // -virtual bool recv(RsRawItem *) = 0; -virtual bool send(RsRawItem *item); +public: + void setServiceServer(p3ServiceServerIface *server); + // + virtual bool recv(RsRawItem *) = 0; + virtual bool send(RsRawItem *item); -virtual RsServiceInfo getServiceInfo() = 0; + virtual RsServiceInfo getServiceInfo() = 0; -virtual int tick() { return 0; } + virtual int tick() { return 0; } - private: + virtual void getItemNames(std::map& names) const {} // This does nothing by default. Service should derive it in order to give info for the UI + +private: p3ServiceServerIface *mServiceServer; // const, no need for mutex. }; @@ -97,10 +99,10 @@ public: virtual ~p3ServiceServerIface() {} -virtual bool recvItem(RsRawItem *) = 0; -virtual bool sendItem(RsRawItem *) = 0; - + virtual bool recvItem(RsRawItem *) = 0; + virtual bool sendItem(RsRawItem *) = 0; + virtual bool getServiceItemNames(uint32_t service_type,std::map& names) =0; }; class p3ServiceServer : public p3ServiceServerIface @@ -108,13 +110,15 @@ class p3ServiceServer : public p3ServiceServerIface public: p3ServiceServer(pqiPublisher *pub, p3ServiceControl *ctrl); -int addService(pqiService *, bool defaultOn); -int removeService(pqiService *); + int addService(pqiService *, bool defaultOn); + int removeService(pqiService *); -bool recvItem(RsRawItem *); -bool sendItem(RsRawItem *); + bool recvItem(RsRawItem *); + bool sendItem(RsRawItem *); -int tick(); + bool getServiceItemNames(uint32_t service_type, std::map& names) ; + + int tick(); public: private: @@ -122,7 +126,7 @@ private: pqiPublisher *mPublisher; // constant no need for mutex. p3ServiceControl *mServiceControl; - RsMutex srvMtx; + RsMutex srvMtx; std::map services; }; diff --git a/libretroshare/src/retroshare/rsservicecontrol.h b/libretroshare/src/retroshare/rsservicecontrol.h index a6d8fde7c..7558764e7 100644 --- a/libretroshare/src/retroshare/rsservicecontrol.h +++ b/libretroshare/src/retroshare/rsservicecontrol.h @@ -109,6 +109,7 @@ virtual ~RsServiceControl() { return; } virtual bool getOwnServices(RsPeerServiceInfo &info) = 0; virtual std::string getServiceName(uint32_t service_id) = 0; +virtual bool getServiceItemNames(uint32_t service_id,std::map& names) = 0; virtual bool getServicesAllowed(const RsPeerId &peerId, RsPeerServiceInfo &info) = 0; virtual bool getServicesProvided(const RsPeerId &peerId, RsPeerServiceInfo &info) = 0; diff --git a/libretroshare/src/rsserver/rsinit.cc b/libretroshare/src/rsserver/rsinit.cc index 47036b691..fd378b286 100644 --- a/libretroshare/src/rsserver/rsinit.cc +++ b/libretroshare/src/rsserver/rsinit.cc @@ -1243,6 +1243,8 @@ int RsServer::StartupRetroShare() pqih = new pqisslpersongrp(serviceCtrl, flags, mPeerMgr); //pqih = new pqipersongrpDummy(none, flags); + serviceCtrl->setServiceServer(pqih) ; + /****** New Ft Server **** !!! */ ftServer *ftserver = new ftServer(mPeerMgr, serviceCtrl); ftserver->setConfigDirectory(rsAccounts->PathAccountDirectory()); diff --git a/retroshare-gui/src/gui/common/RSGraphWidget.cpp b/retroshare-gui/src/gui/common/RSGraphWidget.cpp index 90cf069c2..b7759d846 100644 --- a/retroshare-gui/src/gui/common/RSGraphWidget.cpp +++ b/retroshare-gui/src/gui/common/RSGraphWidget.cpp @@ -99,6 +99,11 @@ QString RSGraphSource::displayValue(float v) const return QString::number(v,'f',_digits) + " " + unitName() ; } +void RSGraphSource::getCumulatedValues(std::vector& vals) const +{ + for(std::map::const_iterator it = _totals.begin();it!=_totals.end();++it) + vals.push_back(it->second) ; +} void RSGraphSource::getCurrentValues(std::vector& vals) const { std::map > >::const_iterator it = _points.begin(); @@ -108,9 +113,9 @@ void RSGraphSource::getCurrentValues(std::vector& vals) const vals.push_back(QPointF( (now - it->second.back().first)/1000.0f,it->second.back().second)) ; } -QString RSGraphSource::legend(int i,float v) const +QString RSGraphSource::legend(int i,float v,bool show_value) const { - return displayName(i) + " (" + displayValue(v) + " )"; + return displayName(i) + (show_value?(" (" + displayValue(v) + ")"):""); } void RSGraphSource::getDataPoints(int index,std::vector& pts,float filter_factor) const @@ -209,11 +214,30 @@ void RSGraphSource::update() } else ++it ; + + updateTotals(); +} + +void RSGraphSource::updateTotals() +{ + // now compute totals + + _totals.clear(); + + for(std::map > >::const_iterator it(_points.begin());it!=_points.end();++it) + { + float& f = _totals[it->first] ; + + f = 0.0f ; + for(std::list >::const_iterator it2=it->second.begin();it2!=it->second.end();++it2) + f += (*it2).second ; + } } void RSGraphSource::reset() { - _points.clear() ; + _points.clear(); + _totals.clear(); } void RSGraphSource::setCollectionTimeLimit(qint64 s) { _time_limit_msecs = s ; } @@ -630,8 +654,19 @@ void RSGraphWidget::paintLegend() { //int bottom = _rec.height(); - std::vector vals ; - _source->getCurrentValues(vals) ; + std::vector vals ; + + if(_flags & RSGRAPH_FLAGS_LEGEND_CUMULATED) + _source->getCumulatedValues(vals) ; + else + { + std::vector cvals ; + _source->getCurrentValues(cvals) ; + + for(uint32_t i=0;idisplayName(i).toStdString()) == _masked_entries.end() ) { - if( _rec.width() - (vals[i].x()-0)*_time_scale < SCALE_WIDTH*fact ) - continue ; +// if( _rec.width() - (vals[i].x()-0)*_time_scale < SCALE_WIDTH*fact ) +// continue ; qreal paintStep = 4*fact+FS; qreal pos = 15*fact+j*paintStep; - QString text = _source->legend(i,vals[i].y()) ; + + QString text = _source->legend(i,vals[i]) ; QPen oldPen = _painter->pen(); _painter->setPen(QPen(getColor(i), Qt::SolidLine)); diff --git a/retroshare-gui/src/gui/common/RSGraphWidget.h b/retroshare-gui/src/gui/common/RSGraphWidget.h index 84a4ee3be..2159ba0dc 100644 --- a/retroshare-gui/src/gui/common/RSGraphWidget.h +++ b/retroshare-gui/src/gui/common/RSGraphWidget.h @@ -69,8 +69,11 @@ public: // return the vector of last values up to date virtual void getCurrentValues(std::vector& vals) const ; + // return the vector of cumulated values up to date + virtual void getCumulatedValues(std::vector& vals) const; + // returns what to display in the legend. Derive this to show additional info. - virtual QString legend(int i,float v) const ; + virtual QString legend(int i, float v, bool show_value=true) const ; // Returns the n^th interpolated value at the given time in floating point seconds backward. virtual void getDataPoints(int index, std::vector& pts, float filter_factor=0.0f) const ; @@ -95,11 +98,13 @@ protected slots: protected: virtual void getValues(std::map& values) const = 0 ;// overload this in your own class to fill in the values you want to display. + void updateTotals(); qint64 getTime() const ; // returns time in ms since RS has started // Storage of collected events. The string is any string used to represent the collected data. std::map > > _points ; + std::map _totals ; QTimer *_timer ; @@ -118,8 +123,9 @@ public: static const uint32_t RSGRAPH_FLAGS_LOG_SCALE_Y = 0x0002 ;// log scale in Y static const uint32_t RSGRAPH_FLAGS_ALWAYS_COLLECT = 0x0004 ;// keep collecting while not displayed static const uint32_t RSGRAPH_FLAGS_PAINT_STYLE_PLAIN = 0x0008 ;// use plain / line drawing style - static const uint32_t RSGRAPH_FLAGS_SHOW_LEGEND = 0x0010 ;// show legend in the graph - static const uint32_t RSGRAPH_FLAGS_PAINT_STYLE_FLAT = 0x0020 ;// do not interpolate, and draw flat colored boxes + static const uint32_t RSGRAPH_FLAGS_SHOW_LEGEND = 0x0010 ;// show legend in the graph + static const uint32_t RSGRAPH_FLAGS_PAINT_STYLE_FLAT = 0x0020 ;// do not interpolate, and draw flat colored boxes + static const uint32_t RSGRAPH_FLAGS_LEGEND_CUMULATED = 0x0040 ;// show the total in the legend rather than current values /** Bandwidth graph style. */ enum GraphStyle diff --git a/retroshare-gui/src/gui/statistics/BWGraph.cpp b/retroshare-gui/src/gui/statistics/BWGraph.cpp index 08c208868..a7451c560 100644 --- a/retroshare-gui/src/gui/statistics/BWGraph.cpp +++ b/retroshare-gui/src/gui/statistics/BWGraph.cpp @@ -107,16 +107,25 @@ void BWGraphSource::update() // remove empty lists + float duration = 0.0f; + for(std::map > >::iterator it=_points.begin();it!=_points.end();) if(it->second.empty()) - { - std::map > >::iterator tmp(it) ; - ++tmp; - _points.erase(it) ; - it=tmp ; - } + { + std::map > >::iterator tmp(it) ; + ++tmp; + _points.erase(it) ; + it=tmp ; + } else + { + float d = it->second.back().first - it->second.front().first; + + if(duration < d) + duration = d ; + ++it ; + } // also clears history @@ -138,11 +147,36 @@ void BWGraphSource::update() break ; } + // now update the totals, and possibly convert into an average if the unit requires it. + + updateTotals(); + + if(_current_unit == UNIT_KILOBYTES) + for(std::map::iterator it(_totals.begin());it!=_totals.end();++it) + it->second /= (duration/1000.0) ; + #ifdef BWGRAPH_DEBUG std::cerr << "Traffic history has size " << mTrafficHistory.size() << std::endl; #endif } +std::string BWGraphSource::makeSubItemName(uint16_t service_id,uint8_t sub_item_type) const +{ + RsServiceInfoWithNames& s(mServiceInfoMap[service_id]) ; + + if(s.item_names.empty()) + return "item #"+QString("%1").arg(sub_item_type,2,16,QChar('0')).toStdString() ; + else + { + std::map::const_iterator it = s.item_names.find(sub_item_type) ; + + if(it == s.item_names.end()) + return "item #"+QString("%1").arg(sub_item_type,2,16,QChar('0')).toStdString() + " (undocumented)"; + + return QString("%1").arg(sub_item_type,2,16,QChar('0')).toStdString()+": " + it->second ; + } +} + void BWGraphSource::convertTrafficClueToValues(const std::list& lst,std::map& vals) const { vals.clear() ; @@ -162,7 +196,7 @@ void BWGraphSource::convertTrafficClueToValues(const std::list& l for(uint32_t i=0;i<256;++i) if(clue_per_sub_id[i].count > 0) - vals["item #"+QString::number(i,16).toStdString()] = (_current_unit == UNIT_KILOBYTES)?(clue_per_sub_id[i].size):(clue_per_sub_id[i].count) ; + vals[makeSubItemName(clue_per_sub_id[i].service_id,i)] = (_current_unit == UNIT_KILOBYTES)?(clue_per_sub_id[i].size):(clue_per_sub_id[i].count) ; } break ; @@ -233,11 +267,14 @@ void BWGraphSource::convertTrafficClueToValues(const std::list& l for(std::list::const_iterator it(lst.begin());it!=lst.end();++it) if(it->service_id == _current_selected_service) + { clue_per_sub_id[it->service_sub_id] += *it ; + clue_per_sub_id[it->service_sub_id].service_id = it->service_id ; + } for(uint32_t i=0;i<256;++i) if(clue_per_sub_id[i].count > 0) - vals["item #"+QString::number(i,16).toStdString()] = (_current_unit == UNIT_KILOBYTES)?(clue_per_sub_id[i].size):(clue_per_sub_id[i].count) ; + vals[makeSubItemName(clue_per_sub_id[i].service_id,i)] = (_current_unit == UNIT_KILOBYTES)?(clue_per_sub_id[i].size):(clue_per_sub_id[i].count) ; } break ; @@ -297,7 +334,11 @@ BWGraphSource::BWGraphSource() rsServiceControl->getOwnServices(rspsi) ; for(std::map::const_iterator it(rspsi.mServiceList.begin());it!=rspsi.mServiceList.end();++it) + { mServiceInfoMap[ (it->first >> 8) & 0xffff ] = it->second ; + + rsServiceControl->getServiceItemNames(it->first,mServiceInfoMap[(it->first >> 8) & 0xffff].item_names) ; + } } void BWGraphSource::getValues(std::map& values) const @@ -359,9 +400,9 @@ QString BWGraphSource::displayValue(float v) const return QString() ; } -QString BWGraphSource::legend(int i,float v) const +QString BWGraphSource::legend(int i,float v,bool show_value) const { - return RSGraphSource::legend(i,v) ;//+ " Total: " + niceNumber(_total_recv) ; + return RSGraphSource::legend(i,v,show_value) ; } QString BWGraphSource::niceNumber(float v) const { @@ -446,6 +487,7 @@ void BWGraphSource::setUnit(int unit) recomputeCurrentCurves() ; } + void BWGraphSource::setDirection(int dir) { if(dir == _current_direction) diff --git a/retroshare-gui/src/gui/statistics/BWGraph.h b/retroshare-gui/src/gui/statistics/BWGraph.h index 865893473..3e2c4b8b2 100644 --- a/retroshare-gui/src/gui/statistics/BWGraph.h +++ b/retroshare-gui/src/gui/statistics/BWGraph.h @@ -13,6 +13,14 @@ public: std::list out_rstcl ; std::list in_rstcl ; }; + class RsServiceInfoWithNames: public RsServiceInfo + { + public: + RsServiceInfoWithNames(const RsServiceInfo& s) : RsServiceInfo(s) {} + RsServiceInfoWithNames(){} + + std::map item_names ; + }; BWGraphSource() ; @@ -25,7 +33,7 @@ public: virtual void getValues(std::map& values) const; virtual QString displayValue(float v) const; - virtual QString legend(int i,float v) const; + virtual QString legend(int i,float v,bool show_value=true) const; virtual void update(); QString unitName() const ; @@ -45,6 +53,7 @@ public: protected: void convertTrafficClueToValues(const std::list &lst, std::map &vals) const; + std::string makeSubItemName(uint16_t service_id,uint8_t sub_item_type) const; void recomputeCurrentCurves() ; std::string visibleFriendName(const RsPeerId &pid) const ; @@ -67,7 +76,7 @@ private: std::map mVisibleFriends ; std::set mVisibleServices ; - mutable std::map mServiceInfoMap ; + mutable std::map mServiceInfoMap ; }; class BWGraph: public RSGraphWidget diff --git a/retroshare-gui/src/gui/statistics/BandwidthStatsWidget.cpp b/retroshare-gui/src/gui/statistics/BandwidthStatsWidget.cpp index b3fd9a063..6ae112803 100644 --- a/retroshare-gui/src/gui/statistics/BandwidthStatsWidget.cpp +++ b/retroshare-gui/src/gui/statistics/BandwidthStatsWidget.cpp @@ -28,13 +28,18 @@ BandwidthStatsWidget::BandwidthStatsWidget(QWidget *parent) ui.bwgraph_BW->setSelector(BWGraphSource::SELECTOR_TYPE_SERVICE,BWGraphSource::GRAPH_TYPE_SUM) ; ui.bwgraph_BW->setUnit(BWGraphSource::UNIT_KILOBYTES) ; + ui.bwgraph_BW->resetFlags(RSGraphWidget::RSGRAPH_FLAGS_LEGEND_CUMULATED) ; + + updateUnitSelection(0); + // Setup connections - QObject::connect(ui.friend_CB ,SIGNAL(currentIndexChanged(int)),this, SLOT( updateFriendSelection(int))) ; - QObject::connect(ui.updn_CB ,SIGNAL(currentIndexChanged(int)),this, SLOT( updateUpDownSelection(int))) ; - QObject::connect(ui.unit_CB ,SIGNAL(currentIndexChanged(int)),this, SLOT( updateUnitSelection(int))) ; - QObject::connect(ui.service_CB,SIGNAL(currentIndexChanged(int)),this, SLOT(updateServiceSelection(int))) ; - QObject::connect(ui.logScale_CB,SIGNAL(toggled(bool)),this, SLOT(toggleLogScale(bool))) ; + QObject::connect(ui.friend_CB ,SIGNAL(currentIndexChanged(int )),this, SLOT( updateFriendSelection(int ))) ; + QObject::connect(ui.updn_CB ,SIGNAL(currentIndexChanged(int )),this, SLOT( updateUpDownSelection(int ))) ; + QObject::connect(ui.unit_CB ,SIGNAL(currentIndexChanged(int )),this, SLOT( updateUnitSelection(int ))) ; + QObject::connect(ui.service_CB ,SIGNAL(currentIndexChanged(int )),this, SLOT(updateServiceSelection(int ))) ; + QObject::connect(ui.legend_CB ,SIGNAL(currentIndexChanged(int )),this, SLOT( updateLegendType(int ))) ; + QObject::connect(ui.logScale_CB,SIGNAL( toggled(bool)),this, SLOT( toggleLogScale(bool))) ; // setup one timer for auto-update @@ -156,6 +161,13 @@ void BandwidthStatsWidget::updateFriendSelection(int n) ui.bwgraph_BW->setSelector(BWGraphSource::SELECTOR_TYPE_FRIEND,BWGraphSource::GRAPH_TYPE_SINGLE,ui.friend_CB->itemData(ci,Qt::UserRole).toString().toStdString()) ; } } +void BandwidthStatsWidget::updateLegendType(int n) +{ + if(n==0) + ui.bwgraph_BW->resetFlags(RSGraphWidget::RSGRAPH_FLAGS_LEGEND_CUMULATED) ; + else + ui.bwgraph_BW->setFlags(RSGraphWidget::RSGRAPH_FLAGS_LEGEND_CUMULATED) ; +} void BandwidthStatsWidget::updateServiceSelection(int n) { if(n == 0) @@ -187,7 +199,13 @@ void BandwidthStatsWidget::updateUpDownSelection(int n) void BandwidthStatsWidget::updateUnitSelection(int n) { if(n==0) + { ui.bwgraph_BW->setUnit(BWGraphSource::UNIT_KILOBYTES) ; + ui.legend_CB->setItemText(1,tr("Average")); + } else + { ui.bwgraph_BW->setUnit(BWGraphSource::UNIT_COUNT) ; + ui.legend_CB->setItemText(1,tr("Total")); + } } diff --git a/retroshare-gui/src/gui/statistics/BandwidthStatsWidget.h b/retroshare-gui/src/gui/statistics/BandwidthStatsWidget.h index 9a835fc57..055555f73 100644 --- a/retroshare-gui/src/gui/statistics/BandwidthStatsWidget.h +++ b/retroshare-gui/src/gui/statistics/BandwidthStatsWidget.h @@ -15,7 +15,8 @@ protected slots: void updateUpDownSelection(int n); void updateUnitSelection(int n); void toggleLogScale(bool b); - + void updateLegendType(int n); + private: Ui::BwStatsWidget ui; diff --git a/retroshare-gui/src/gui/statistics/BandwidthStatsWidget.ui b/retroshare-gui/src/gui/statistics/BandwidthStatsWidget.ui index e99058ac3..fdfefb99b 100644 --- a/retroshare-gui/src/gui/statistics/BandwidthStatsWidget.ui +++ b/retroshare-gui/src/gui/statistics/BandwidthStatsWidget.ui @@ -6,7 +6,7 @@ 0 0 - 1128 + 1148 385 @@ -14,7 +14,16 @@ Form - + + 0 + + + 0 + + + 0 + + 0 @@ -103,6 +112,27 @@ + + + + Legend: + + + + + + + + Current + + + + + Total + + + + From 969b5ce1f1260160e0bfc0be2f59253777c27b8c Mon Sep 17 00:00:00 2001 From: Phenom Date: Fri, 21 Apr 2017 15:57:57 +0200 Subject: [PATCH 14/39] Fix MacOSX compilation. --- retroshare-gui/src/gui/elastic/fft.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/retroshare-gui/src/gui/elastic/fft.h b/retroshare-gui/src/gui/elastic/fft.h index 12d460c24..0b5c48ad7 100644 --- a/retroshare-gui/src/gui/elastic/fft.h +++ b/retroshare-gui/src/gui/elastic/fft.h @@ -104,7 +104,11 @@ public: w[nwh] = cos(delta * nwh); w[nwh + 1] = w[nwh]; for (j = 2; j <= nwh - 2; j += 2) { +#ifdef __APPLE__ + __sincos(delta*j,&y,&x); +#else sincos(delta*j,&y,&x) ; +#endif //x = cos(delta * j); //y = sin(delta * j); w[j] = x; From 936dcbabb344e46b95c396fb596fc41febe63d98 Mon Sep 17 00:00:00 2001 From: Phenom Date: Fri, 21 Apr 2017 18:50:36 +0200 Subject: [PATCH 15/39] Fix UnitTest compilation. --- tests/unittests/libretroshare/gxs/nxs_test/nxstesthub.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unittests/libretroshare/gxs/nxs_test/nxstesthub.cc b/tests/unittests/libretroshare/gxs/nxs_test/nxstesthub.cc index 216f971c1..36b288341 100644 --- a/tests/unittests/libretroshare/gxs/nxs_test/nxstesthub.cc +++ b/tests/unittests/libretroshare/gxs/nxs_test/nxstesthub.cc @@ -53,6 +53,7 @@ public: { return recvItem(i); } + bool getServiceItemNames(uint32_t /*service_type*/, std::map& /*names*/) { return false; } private: RsPeerId mPeerId; RecvPeerItemIface* mRecvIface; From 8c0b7ce776bfc77f4d03ec269d3f3ffbec250d90 Mon Sep 17 00:00:00 2001 From: Konrad Date: Fri, 21 Apr 2017 23:44:00 +0200 Subject: [PATCH 16/39] Fixed: Responds sends now correct time difference --- libresapi/src/api/IdentityHandler.cpp | 4 ++-- libresapi/src/api/PeersHandler.cpp | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libresapi/src/api/IdentityHandler.cpp b/libresapi/src/api/IdentityHandler.cpp index 67e5cb4c6..2990a745c 100644 --- a/libresapi/src/api/IdentityHandler.cpp +++ b/libresapi/src/api/IdentityHandler.cpp @@ -413,7 +413,7 @@ void IdentityHandler::handleGetIdentityDetails(Request& req, Response& resp) resp.mDataStream << makeKeyValue("pgp_name", pgp_name); time_t now = time(NULL); - resp.mDataStream << makeKeyValue("last_usage", std::to_string(now - data.mLastUsageTS)); + resp.mDataStream << makeKeyValue("last_usage", difftime(now, data.mLastUsageTS)); bool isAnonymous = false; if(!data.mPgpKnown) @@ -468,7 +468,7 @@ void IdentityHandler::handleGetIdentityDetails(Request& req, Response& resp) for(std::map::const_iterator it(details.mUseCases.begin()); it != details.mUseCases.end(); ++it) { - usagesStream.getStreamToMember() << makeKeyValue("usage_time", std::to_string(now - it->second)); + usagesStream.getStreamToMember() << makeKeyValue("usage_time", difftime(now, data.mLastUsageTS)); usagesStream.getStreamToMember() << makeKeyValue("usage_service", (int)(it->first.mServiceId)); usagesStream.getStreamToMember() << makeKeyValue("usage_case", (int)(it->first.mUsageCode)); } diff --git a/libresapi/src/api/PeersHandler.cpp b/libresapi/src/api/PeersHandler.cpp index 6649acdcb..dd03f8351 100644 --- a/libresapi/src/api/PeersHandler.cpp +++ b/libresapi/src/api/PeersHandler.cpp @@ -7,6 +7,7 @@ #include #include +#include #include "Operators.h" #include "ApiTypes.h" @@ -745,11 +746,12 @@ void PeersHandler::handleGetNodeOptions(Request& req, Response& resp) return; } + time_t now = time(NULL); resp.mDataStream << makeKeyValue("peer_id", detail.id.toStdString()); resp.mDataStream << makeKeyValue("name", detail.name); resp.mDataStream << makeKeyValue("location", detail.location); resp.mDataStream << makeKeyValue("pgp_id", detail.gpg_id.toStdString()); - resp.mDataStream << makeKeyValue("last_contact", detail.lastConnect); + resp.mDataStream << makeKeyValue("last_contact", difftime(now, detail.lastConnect)); std::string status_message = mRsMsgs->getCustomStateString(detail.id); resp.mDataStream << makeKeyValueReference("status_message", status_message); From 8b9c447063a13f4b2c567e8be378a8c270487003 Mon Sep 17 00:00:00 2001 From: electron128 Date: Sat, 22 Apr 2017 10:13:23 +0200 Subject: [PATCH 17/39] fixed possible crash and return value in rsGetHostByName(), thanks to Kotyara for reporting this --- libretroshare/src/util/rsnet.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libretroshare/src/util/rsnet.cc b/libretroshare/src/util/rsnet.cc index 63501511b..8b8c9ef82 100644 --- a/libretroshare/src/util/rsnet.cc +++ b/libretroshare/src/util/rsnet.cc @@ -81,15 +81,18 @@ bool rsGetHostByName(const std::string& hostname, in_addr& returned_addr) addrinfo *info = NULL; int res = getaddrinfo(hostname.c_str(),NULL,NULL,&info) ; + bool ok = true; if(res > 0 || info == NULL || info->ai_addr == NULL) { std::cerr << "(EE) getaddrinfo returned error " << res << " on string \"" << hostname << "\"" << std::endl; returned_addr.s_addr = 0 ; + ok = false; } else returned_addr.s_addr = ((sockaddr_in*)info->ai_addr)->sin_addr.s_addr ; - freeaddrinfo(info) ; + if(info) + freeaddrinfo(info) ; #ifdef DEPRECATED_TO_REMOVE #if defined(WINDOWS_SYS) || defined(__APPLE__) || defined(__HAIKU__) @@ -123,7 +126,7 @@ bool rsGetHostByName(const std::string& hostname, in_addr& returned_addr) returned_addr.s_addr = *(unsigned long*) (result->h_addr); #endif - return true ; + return ok; } bool isValidNet(const struct in_addr *addr) From f571b05693e2e886cbb062cdf5636e945e5b607f Mon Sep 17 00:00:00 2001 From: Konrad Date: Sat, 22 Apr 2017 11:06:56 +0200 Subject: [PATCH 18/39] Added: Checking if the vector is empty; Changed: Grouped values into one member --- libresapi/src/api/IdentityHandler.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/libresapi/src/api/IdentityHandler.cpp b/libresapi/src/api/IdentityHandler.cpp index 2990a745c..1306f9a54 100644 --- a/libresapi/src/api/IdentityHandler.cpp +++ b/libresapi/src/api/IdentityHandler.cpp @@ -388,6 +388,12 @@ void IdentityHandler::handleGetIdentityDetails(Request& req, Response& resp) return; } + if(datavector.empty()) + { + resp.setFail(); + return; + } + data = datavector[0]; resp.mDataStream << makeKeyValue("gxs_name", data.mMeta.mGroupName); @@ -468,9 +474,10 @@ void IdentityHandler::handleGetIdentityDetails(Request& req, Response& resp) for(std::map::const_iterator it(details.mUseCases.begin()); it != details.mUseCases.end(); ++it) { - usagesStream.getStreamToMember() << makeKeyValue("usage_time", difftime(now, data.mLastUsageTS)); - usagesStream.getStreamToMember() << makeKeyValue("usage_service", (int)(it->first.mServiceId)); - usagesStream.getStreamToMember() << makeKeyValue("usage_case", (int)(it->first.mUsageCode)); + usagesStream.getStreamToMember() + << makeKeyValue("usage_time", difftime(now, data.mLastUsageTS)) + << makeKeyValue("usage_service", (int)(it->first.mServiceId)) + << makeKeyValue("usage_case", (int)(it->first.mUsageCode)); } resp.setOk(); From 0e087db807dfff94cdab04dfc763e6fe3b26689a Mon Sep 17 00:00:00 2001 From: defnax Date: Sat, 22 Apr 2017 17:32:59 +0200 Subject: [PATCH 19/39] Fixed to use right icons for context menu actions --- retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp index 5c479005c..6afa8dbdd 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp @@ -60,6 +60,7 @@ /* Images for context menu icons */ #define IMAGE_MESSAGE ":/images/mail_new.png" #define IMAGE_MESSAGEREPLY ":/images/mail_reply.png" +#define IMAGE_MESSAGEEDIT ":/images/edit_16.png" #define IMAGE_MESSAGEREMOVE ":/images/mail_delete.png" #define IMAGE_DOWNLOAD ":/images/start.png" #define IMAGE_DOWNLOADALL ":/images/startall.png" @@ -485,7 +486,7 @@ void GxsForumThreadWidget::threadListCustomPopupMenu(QPoint /*point*/) QMenu contextMnu(this); - QAction *editAct = new QAction(QIcon(IMAGE_MESSAGEREPLY), tr("Edit"), &contextMnu); + QAction *editAct = new QAction(QIcon(IMAGE_MESSAGEEDIT), tr("Edit"), &contextMnu); connect(editAct, SIGNAL(triggered()), this, SLOT(editforummessage())); QAction *replyAct = new QAction(QIcon(IMAGE_MESSAGEREPLY), tr("Reply"), &contextMnu); @@ -531,7 +532,7 @@ void GxsForumThreadWidget::threadListCustomPopupMenu(QPoint /*point*/) QAction *markMsgAsUnreadChildren = new QAction(QIcon(":/images/message-mail.png"), tr("Mark as unread") + " (" + tr ("with children") + ")", &contextMnu); connect(markMsgAsUnreadChildren, SIGNAL(triggered()), this, SLOT(markMsgAsUnreadChildren())); - QAction *showinpeopleAct = new QAction(QIcon(":/images/message-mail.png"), tr("Show author in people tab"), &contextMnu); + QAction *showinpeopleAct = new QAction(QIcon(":/images/info16.png"), tr("Show author in people tab"), &contextMnu); connect(showinpeopleAct, SIGNAL(triggered()), this, SLOT(showInPeopleTab())); if (IS_GROUP_SUBSCRIBED(mSubscribeFlags)) { From 4c326f5e808f261bb3e4522d6cbaba2927224dc9 Mon Sep 17 00:00:00 2001 From: Phenom Date: Sun, 23 Apr 2017 10:27:18 +0200 Subject: [PATCH 20/39] Fix Relay setting page. --- retroshare-gui/src/gui/settings/RelayPage.cpp | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/retroshare-gui/src/gui/settings/RelayPage.cpp b/retroshare-gui/src/gui/settings/RelayPage.cpp index 258bc05aa..3124f40db 100644 --- a/retroshare-gui/src/gui/settings/RelayPage.cpp +++ b/retroshare-gui/src/gui/settings/RelayPage.cpp @@ -29,6 +29,7 @@ #include #include #include +#include "util/misc.h" #include @@ -127,35 +128,37 @@ void RelayPage::load() uint32_t count; uint32_t bandwidth; rsDht->getRelayAllowance(RSDHT_RELAY_CLASS_FRIENDS, count, bandwidth); - ui.noFriendSpinBox->setValue(count); - ui.bandFriendSpinBox->setValue(bandwidth / 1000); + whileBlocking(ui.noFriendSpinBox)->setValue(count); + whileBlocking(ui.bandFriendSpinBox)->setValue(bandwidth / 1000); rsDht->getRelayAllowance(RSDHT_RELAY_CLASS_FOF, count, bandwidth); - ui.noFOFSpinBox->setValue(count); - ui.bandFOFSpinBox->setValue(bandwidth / 1000); + whileBlocking(ui.noFOFSpinBox)->setValue(count); + whileBlocking(ui.bandFOFSpinBox)->setValue(bandwidth / 1000); rsDht->getRelayAllowance(RSDHT_RELAY_CLASS_GENERAL, count, bandwidth); - ui.noGeneralSpinBox->setValue(count); - ui.bandGeneralSpinBox->setValue(bandwidth / 1000); + whileBlocking(ui.noGeneralSpinBox)->setValue(count); + whileBlocking(ui.bandGeneralSpinBox)->setValue(bandwidth / 1000); + + updateTotals(); uint32_t relayMode = rsDht->getRelayMode(); if (relayMode & RSDHT_RELAY_ENABLED) { - ui.enableCheckBox->setCheckState(Qt::Checked); + whileBlocking(ui.enableCheckBox)->setCheckState(Qt::Checked); if ((relayMode & RSDHT_RELAY_MODE_MASK) == RSDHT_RELAY_MODE_OFF) { - ui.serverCheckBox->setCheckState(Qt::Unchecked); + whileBlocking(ui.serverCheckBox)->setCheckState(Qt::Unchecked); } else { - ui.serverCheckBox->setCheckState(Qt::Checked); + whileBlocking(ui.serverCheckBox)->setCheckState(Qt::Checked); } } else { - ui.enableCheckBox->setCheckState(Qt::Unchecked); - ui.serverCheckBox->setCheckState(Qt::Unchecked); + whileBlocking(ui.enableCheckBox)->setCheckState(Qt::Unchecked); + whileBlocking(ui.serverCheckBox)->setCheckState(Qt::Unchecked); } loadServers(); From 5b3b903603742a7717d7e5f372df8f13140089f7 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 23 Apr 2017 17:33:21 +0200 Subject: [PATCH 21/39] added missing line for ubuntu zesty --- build_scripts/Debian+Ubuntu/makeSourcePackage.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build_scripts/Debian+Ubuntu/makeSourcePackage.sh b/build_scripts/Debian+Ubuntu/makeSourcePackage.sh index 5cbb59f24..2e6f4305a 100755 --- a/build_scripts/Debian+Ubuntu/makeSourcePackage.sh +++ b/build_scripts/Debian+Ubuntu/makeSourcePackage.sh @@ -116,6 +116,8 @@ for i in ${dist}; do if test "${i}" = "lucid" ; then cp ../control.ubuntu_lucid debian/control + elif test "${i}" = "zesty" ; then + cp ../control.zesty debian/control elif test "${i}" = "squeeze" ; then cp ../control.squeeze_bubba3 debian/control elif test "${i}" = "precise" ; then From c738026eb8f874620ecaf174b5477f4d5039eae4 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 23 Apr 2017 17:48:39 +0200 Subject: [PATCH 22/39] updated ubuntu changelog --- build_scripts/Debian+Ubuntu/changelog | 194 ++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) diff --git a/build_scripts/Debian+Ubuntu/changelog b/build_scripts/Debian+Ubuntu/changelog index 15c1216c6..bb6fcd9b7 100644 --- a/build_scripts/Debian+Ubuntu/changelog +++ b/build_scripts/Debian+Ubuntu/changelog @@ -1,5 +1,199 @@ retroshare06 (0.6.2-1.XXXXXX~YYYYYY) YYYYYY; urgency=low + 5b3b903 csoler Sun, 23 Apr 2017 17:33:21 +0200 added missing line for ubuntu zesty + 73bfc27 csoler Sun, 23 Apr 2017 17:33:50 +0200 Merge pull request #784 from PhenomRetroShare/Fix_RelaySettingsPage + 4c326f5 Phenom Sun, 23 Apr 2017 10:27:18 +0200 Fix Relay setting page. + 0e087db defnax Sat, 22 Apr 2017 17:32:59 +0200 Fixed to use right icons for context menu actions + 8b9c447 electr Sat, 22 Apr 2017 10:13:23 +0200 fixed possible crash and return value in rsGetHostByName(), thanks to Kotyara for reporting this + 4ab6021 csoler Fri, 21 Apr 2017 19:45:30 +0200 Merge pull request #782 from PhenomRetroShare/Fix_MacOSX_Compilation + 936dcba Phenom Fri, 21 Apr 2017 18:50:36 +0200 Fix UnitTest compilation. + 969b5ce Phenom Fri, 21 Apr 2017 15:57:57 +0200 Fix MacOSX compilation. + 7400a8d csoler Thu, 20 Apr 2017 20:59:12 +0200 Merge pull request #780 from csoler/v0.6-ImprovedGUI + 5f8bf03 csoler Thu, 20 Apr 2017 20:54:51 +0200 added mechanism to allow services to document the names of their items, and improved bandwidth graph to show names for GXS services. Other services still need to supply their own names + ccfd12b csoler Wed, 19 Apr 2017 18:53:49 +0200 Merge pull request #778 from csoler/v0.6-ImprovedGUI + f406b81 csoler Wed, 19 Apr 2017 18:46:58 +0200 removed all FFT code and cleaned up deleted code in graphwidget.cpp + 1da89dd csoler Wed, 19 Apr 2017 17:16:30 +0200 changed FFT code in graph widget into a more efficient one, with free licence + e95ddb9 csoler Tue, 18 Apr 2017 20:28:36 +0200 Merge pull request #767 from PhenomRetroShare/Fix_CommentWithLineReturn + 5f969e7 csoler Tue, 18 Apr 2017 20:27:20 +0200 Merge pull request #776 from PhenomRetroShare/Fix_ClangWarnings + 3ab39c6 csoler Tue, 18 Apr 2017 20:26:14 +0200 Merge pull request #777 from PhenomRetroShare/Fix_EncodeRadixInRSLinks + 3c5e61a Phenom Tue, 18 Apr 2017 17:36:43 +0200 Encode Radix in RSLinks. + 3733137 Phenom Tue, 18 Apr 2017 11:25:41 +0200 Fix Clang warnings: implicit conversion + 7d9a803 Phenom Tue, 18 Apr 2017 11:18:10 +0200 Fix Clang warnings: bdnet_inet_ntoa C-linkage + 4faaaf7 csoler Mon, 17 Apr 2017 22:03:48 +0200 Merge pull request #775 from csoler/v0.6-PRTest + 87dd614 Phenom Fri, 7 Apr 2017 19:32:19 +0200 Fix Clang Warnings: private field 'encoding_debug_file' is not used + 4f939b2 Phenom Fri, 7 Apr 2017 19:29:27 +0200 Fix Clang warnings: unused function 'set_item_background' + 76f7573 Phenom Fri, 7 Apr 2017 18:48:40 +0200 Fix Clang warnings: comparison of array != a null pointer is always true + 0bbd149 Phenom Fri, 7 Apr 2017 18:42:22 +0200 Fix Clang warnings: comparison of integers of different signs + a476a81 Phenom Fri, 7 Apr 2017 18:40:02 +0200 Fix Clang warnings: function 'update_children_background' is not needed + d8a7313 Phenom Fri, 7 Apr 2017 18:32:55 +0200 Fix Clang warnings: implicit conversion from 'double' to 'int' + 19196e2 Phenom Fri, 7 Apr 2017 18:21:49 +0200 Fix Clang warnings: ariable 'status' is used uninitialized + a3a53b9 Phenom Fri, 7 Apr 2017 18:19:42 +0200 Fix Clang warnings: unused parameter 'req' + 94ac821 Phenom Wed, 29 Mar 2017 18:13:17 +0200 Fix Clang warnings: Unused variable Pi + fd92bca Phenom Tue, 28 Mar 2017 21:18:25 +0200 Fix Clang warnings: variable 'layout' is used uninitialized + 8d85cf5 Phenom Tue, 28 Mar 2017 21:16:05 +0200 Fix Clang warnings: 'xxxWidget::sizeHint' hides overloaded vf + 6f2d7bb Phenom Sun, 19 Mar 2017 10:51:48 +0100 Fix Clang warnings: implicit conversion from 'double' to 'int' + 07b67e9 Phenom Sun, 19 Mar 2017 10:40:34 +0100 Fix Clang warnings: 'PopupDistantChatDialog::init' hides overloaded virtual function + eea49d9 Phenom Sat, 18 Mar 2017 11:56:11 +0100 Fix Clang warnings: change ChatDialog::init definition + 9319caf Phenom Sat, 18 Mar 2017 11:32:56 +0100 Fix Clang warnings: 'Node::advance' hides overloaded virtual function + 13c8f7d Phenom Sat, 18 Mar 2017 11:28:29 +0100 Fix Clang warnings: Infinite recursion + e0225ef Phenom Sat, 18 Mar 2017 11:19:42 +0100 Fix Clang warnings: 'ChatLobbyDialog::init' hides overloaded virtual function + de4f6c0 Phenom Sat, 18 Mar 2017 10:42:38 +0100 Fix Clang warnings: Z-order assignment to spacer + 32eeb95 Phenom Sat, 18 Mar 2017 10:25:23 +0100 Fix Clang warnings: unused private field + 4ac3b3f Phenom Sat, 18 Mar 2017 10:20:57 +0100 Fix Clang warnings: implicit conversion of NULL to bool + e83104e Phenom Sat, 18 Mar 2017 10:19:31 +0100 Fix Clang warnings: Add author and date to #warning + 039908b Phenom Thu, 16 Mar 2017 22:58:06 +0100 Fix Clang warnings: private field not used + 872f42b Phenom Thu, 16 Mar 2017 22:55:18 +0100 Fix Clang warnings: Overloaded vf hide in pluginmanager + 2204309 Phenom Thu, 16 Mar 2017 22:11:33 +0100 Fix Clang warnings: extraneous parentheses + dc533b1 Phenom Thu, 16 Mar 2017 22:01:22 +0100 Fix Clang warnings: private field not used + 6532150 Phenom Thu, 16 Mar 2017 21:04:38 +0100 Fix Clang warnings: Overloaded vf hide in p3dhtmgr + 5bc6558 Phenom Thu, 16 Mar 2017 18:28:48 +0100 Fix Clang warnings: explicitly assigning value to itself + 6fecac5 Phenom Thu, 16 Mar 2017 17:50:25 +0100 Fix Clang warnings: Overloaded vf hide + cf963c0 Phenom Wed, 15 Mar 2017 20:41:39 +0100 Fix Clang warnings: struct declared as class + 105840a Phenom Wed, 15 Mar 2017 19:03:39 +0100 Fix Clang Warning: Overloaded vf hide + da4b168 Phenom Wed, 15 Mar 2017 18:55:24 +0100 Fix Clang warnings: mFns is not used + cbc264f Phenom Wed, 15 Mar 2017 18:53:30 +0100 Fix clang warning:Implicit conversion from enumeration + b2e37fe csoler Sat, 15 Apr 2017 20:24:06 +0200 Merge pull request #773 from csoler/v0.6-Identity + 273aae7 csoler Sat, 15 Apr 2017 19:01:13 +0200 fixed sharing of own identity + 98e1a6d electr Thu, 13 Apr 2017 14:12:46 +0200 Merge pull request #770 from Sonetio/fix_reselecting_accounts + 144d570 Konrad Thu, 13 Apr 2017 13:40:30 +0200 Fixed: Thread safe access to RsControlModule member variables + dcc8c6e Konrad Thu, 13 Apr 2017 13:31:32 +0200 Changed: Using PeersHandler::mRsPeers instead of rsPeers + a382d68 electr Thu, 13 Apr 2017 09:22:19 +0200 Merge pull request #769 from electron128/fix-gui-multiinstance + aa81cc1 Konrad Wed, 12 Apr 2017 20:24:18 +0200 Added: Functions for handling PGP account details requests + 9402b8e Konrad Mon, 10 Apr 2017 23:42:22 +0200 Fixed: mFixedPassword remained empty after logging + e1350a0 Konrad Mon, 10 Apr 2017 22:58:23 +0200 Fixed: Re-selecting accounts via RsControlModule; Added: Sending feedback about incorrect password + 3130ec9 csoler Mon, 10 Apr 2017 20:02:14 +0200 added GUI async call to ID serialised data. Allows to copy+paste identities. + 4c9b620 electr Sun, 9 Apr 2017 10:26:18 +0200 fixed --base-dir command line argument in rs-gui when running multiple instances. Only forward "link" and "rsfile" arguments to a running instance. Start a new instance if other arguments are present. + 7f12ca2 electr Sun, 9 Apr 2017 09:57:48 +0200 fixed name of local socket where RS waits for rslinks etc. + d66e653 csoler Sat, 8 Apr 2017 23:39:05 +0200 fixed bug in deserialisation of group informaiton + 54cd402 csoler Sat, 8 Apr 2017 21:43:07 +0200 fixed a few bugs in latest identity link code + 6d29038 csoler Sat, 8 Apr 2017 21:12:48 +0200 added RSLink for GXS identities + 4f5da86 csoler Sat, 8 Apr 2017 19:07:33 +0200 added method to serialise/deserialise groups to/from memory and export of GxsIdentities to memory chunk in radix format + f175533 Phenom Sat, 8 Apr 2017 14:06:47 +0200 Fix comment view when they have line return. + 4067c95 electr Wed, 5 Apr 2017 18:49:32 +0200 Merge pull request #760 from Sonetio/windows_service + 6e65fcd Konrad Sat, 1 Apr 2017 14:32:49 +0200 Removed: Unused #include statement + 8543525 Konrad Sat, 1 Apr 2017 14:28:55 +0200 Fixed: Linker problem + fbc1bb4 Konrad Wed, 29 Mar 2017 16:06:39 +0200 Added: function for handling autosubscribing lobbies + 22956be Konrad Tue, 28 Mar 2017 11:24:16 +0200 Deleted: functions for hadling particular lobbies types in ChatHandler + 6e53002 Konrad Tue, 28 Mar 2017 11:20:51 +0200 Added: tokens in PeersHandler + efd6ce3 Konrad Tue, 28 Mar 2017 11:19:50 +0200 Changed: Simplified asking for deferred self signature + 5694581 Konrad Tue, 28 Mar 2017 11:18:27 +0200 Changed: Qt dependecies are optional + 4031e49 Konrad Mon, 27 Mar 2017 16:11:04 +0200 Deleted: unused stateTokens + c33107c Konrad Sun, 26 Mar 2017 19:12:04 +0200 Fixed: backward comptiblity + bef7540 Konrad Sun, 26 Mar 2017 15:11:07 +0200 Fixed building on Travis CI + dbcf2d2 csoler Sat, 25 Mar 2017 20:27:18 +0100 Merge pull request #756 from RetroPooh/guistuff + 04af39f csoler Sat, 25 Mar 2017 20:24:40 +0100 Merge pull request #754 from PhenomRetroShare/Fix_WinNoSQLCipherCompil + ccb632a csoler Sat, 25 Mar 2017 19:26:12 +0100 Merge pull request #749 from PhenomRetroShare/Fix_WindowsHeightAtFirstStart + 8624c93 Konrad Sat, 25 Mar 2017 18:33:35 +0100 Added functions for hadling particular lobbies types to ChatHandler + 194878a Konrad Sat, 25 Mar 2017 18:31:13 +0100 Added functions for handling own and not own identities to IdentityHandler + cb32f30 Konrad Sat, 25 Mar 2017 18:28:31 +0100 Added states handling to PeersHandler + 28d37c2 Konrad Sat, 25 Mar 2017 18:25:26 +0100 Added password storing to RsControlModule for GUI benefits + 39967b7 Konrad Sat, 25 Mar 2017 18:23:28 +0100 Added name of requests to be used by GUI + ae95b49 Konrad Sat, 25 Mar 2017 18:20:53 +0100 Added SettingsHandler to handle response to settings requests + cb04134 Konrad Sat, 25 Mar 2017 18:15:47 +0100 Added Windows support to libresapi when working with retroshare_android_service + b0d2249 Konrad Sat, 25 Mar 2017 18:12:39 +0100 Added Windows support to retroshare-android-service + f5e7217 RetroP Tue, 21 Mar 2017 17:24:59 +0300 statistics - router - fix bold marking for tunnel speeds over 1mbs + 85cfda1 RetroP Tue, 21 Mar 2017 16:52:40 +0300 add tree item counters for channels,forums,posted + 50c81d7 RetroP Tue, 21 Mar 2017 16:41:39 +0300 chat lobby list - mark signed lobbies with color + 000dabf RetroP Tue, 21 Mar 2017 15:02:46 +0300 chat lobby list - add tree item counters + 19bd51d RetroP Tue, 21 Mar 2017 14:57:06 +0300 searchdialog - mark current downloads green + 5efa8e3 Phenom Fri, 17 Mar 2017 22:14:14 +0100 Fix Windows Compilation with CONFIG+=no_sqlcipher + ca0521c csoler Thu, 16 Mar 2017 21:01:27 +0100 allowed to edit subject hen editing forum posts. Only the latest subject is visible + 107d48f Phenom Wed, 15 Mar 2017 22:50:51 +0100 Fix windows height at first start. + 2046dbe csoler Wed, 15 Mar 2017 20:53:01 +0100 merged latest fixes from official 0.6.2 release branch + e4fad45 csoler Wed, 15 Mar 2017 20:51:40 +0100 fixed layout in ConfCertDialog, removed overnumerous tabs + 2114374 csoler Wed, 15 Mar 2017 19:26:07 +0100 fixed update of Tor proxy address in hidden nodes server page + 44f2971 csoler Tue, 14 Mar 2017 20:04:22 +0100 Merge pull request #682 from csoler/v0.6-EditPosts + a0d1089 csoler Sat, 11 Mar 2017 18:15:35 +0100 added branch parameter to makeSourcePackage script + fdab480 csoler Sat, 11 Mar 2017 18:10:14 +0100 added minimum version number for debian stretch + 733b114 thunde Fri, 10 Mar 2017 15:57:40 +0100 Updated languages from Transifex + ed5779f csoler Fri, 10 Mar 2017 15:39:22 +0100 Merge pull request #743 from mestaritonttu/patch-22 + 69c3df6 csoler Fri, 10 Mar 2017 15:36:50 +0100 fixed bug in total item size estimation in pqiqosstreamer due to item slicing + c377bf3 csoler Fri, 10 Mar 2017 15:12:10 +0100 fixed debug output for groups with no data + fd84639 csoler Fri, 10 Mar 2017 15:05:41 +0100 removed some debug info + c87de3e csoler Fri, 10 Mar 2017 10:48:40 +0100 fixed mistake in pointer handling + cf2edb5 csoler Thu, 9 Mar 2017 22:47:06 +0100 fixed memory leak in deleteGroup and removed unnecessary pointer in the functions called below + a545481 csoler Thu, 9 Mar 2017 22:05:06 +0100 fixed memory leak when receving multi-chunk file lists + 5b819eb csoler Thu, 9 Mar 2017 20:59:01 +0100 added missing virtual destructor causing a memory leak + 1f8fd95 csoler Thu, 9 Mar 2017 20:48:26 +0100 fixed uninitialised memory read in chacha20 test code + d5f2ae8 csoler Thu, 9 Mar 2017 20:39:12 +0100 fixed memory leak recently introduced with openssl-1.1.0 changes + f76454d csoler Thu, 9 Mar 2017 13:05:03 +0100 updated full pipeline packaging script for debian + 999e845 mestar Wed, 8 Mar 2017 13:17:34 +0200 Fix grammar + e6cf628 csoler Tue, 7 Mar 2017 21:58:59 +0100 Merge pull request #740 from RetroPooh/trstats + 283a2ee csoler Tue, 7 Mar 2017 21:54:56 +0100 Merge pull request #717 from PhenomRetroShare/Fix_SettingListWidth + b3b2a4b csoler Tue, 7 Mar 2017 21:54:10 +0100 Merge pull request #726 from mestaritonttu/patch-8 + bbc27b2 csoler Tue, 7 Mar 2017 21:53:21 +0100 Merge pull request #736 from mestaritonttu/patch-18 + 3d0c28d csoler Tue, 7 Mar 2017 21:52:19 +0100 Merge pull request #724 from mestaritonttu/patch-6 + ed22b48 csoler Tue, 7 Mar 2017 21:51:51 +0100 Merge pull request #738 from mestaritonttu/patch-20 + 376be42 csoler Tue, 7 Mar 2017 21:51:13 +0100 Merge pull request #739 from mestaritonttu/patch-21 + b3578f6 csoler Tue, 7 Mar 2017 21:50:20 +0100 Merge pull request #734 from mestaritonttu/patch-16 + d9c084b csoler Tue, 7 Mar 2017 21:49:52 +0100 Merge pull request #730 from mestaritonttu/patch-12 + 5bad326 csoler Tue, 7 Mar 2017 21:49:14 +0100 Merge pull request #725 from mestaritonttu/patch-7 + ec21698 csoler Tue, 7 Mar 2017 21:48:30 +0100 Merge pull request #727 from mestaritonttu/patch-9 + 7d8e06b csoler Tue, 7 Mar 2017 21:47:43 +0100 Merge pull request #732 from mestaritonttu/patch-14 + f3e29bd csoler Tue, 7 Mar 2017 21:47:00 +0100 Merge pull request #731 from mestaritonttu/patch-13 + 17c44db csoler Tue, 7 Mar 2017 21:46:21 +0100 Merge pull request #733 from mestaritonttu/patch-15 + 5f9f061 csoler Tue, 7 Mar 2017 21:45:50 +0100 Merge pull request #735 from mestaritonttu/patch-17 + 8881a44 csoler Tue, 7 Mar 2017 21:45:11 +0100 Merge pull request #737 from mestaritonttu/patch-19 + 160c289 csoler Tue, 7 Mar 2017 21:44:42 +0100 Merge pull request #728 from mestaritonttu/patch-10 + 22308bc csoler Tue, 7 Mar 2017 21:44:14 +0100 Merge pull request #729 from mestaritonttu/patch-11 + fedffd7 csoler Tue, 7 Mar 2017 21:43:36 +0100 Merge pull request #723 from mestaritonttu/patch-5 + d3f0f9d RetroP Tue, 7 Mar 2017 17:50:13 +0300 router stats - mark active tunnels bold + 87f9dba mestar Tue, 7 Mar 2017 14:05:21 +0200 Improvements and typo fixes in strings + 222cf48 mestar Tue, 7 Mar 2017 14:03:05 +0200 Various improvements and fixes to strings + 83283d9 mestar Tue, 7 Mar 2017 13:58:43 +0200 Remove extra your + 7005126 mestar Tue, 7 Mar 2017 13:57:10 +0200 Added whitespace to strings + 6ec5415 mestar Tue, 7 Mar 2017 13:55:02 +0200 ASCII uppercase + 28d2e27 mestar Tue, 7 Mar 2017 13:53:08 +0200 Remove whitespace from string + 931531b mestar Tue, 7 Mar 2017 13:51:28 +0200 Fix typo + 65c7ca7 mestar Tue, 7 Mar 2017 13:49:57 +0200 Clarify sorting by posts + 21b7861 mestar Tue, 7 Mar 2017 13:48:14 +0200 Fix grammar + ba18fcd mestar Tue, 7 Mar 2017 13:45:31 +0200 Fix grammar + a4c2015 mestar Tue, 7 Mar 2017 13:41:45 +0200 Fix typos + 6b4f7e3 mestar Tue, 7 Mar 2017 13:39:39 +0200 Removed extra "to" + b444567 mestar Tue, 7 Mar 2017 13:34:53 +0200 Added period + 400dde9 mestar Tue, 7 Mar 2017 13:09:04 +0200 Added whitespace + c9a4a55 mestar Tue, 7 Mar 2017 13:06:22 +0200 Fix grammar + 86e7243 mestar Tue, 7 Mar 2017 12:56:25 +0200 Fix typos + d7dc9cc mestar Tue, 7 Mar 2017 12:53:18 +0200 Whitespace inside

+ a518225 csoler Tue, 7 Mar 2017 11:27:17 +0100 Merge pull request #716 from felisucoibi/master + 6a6bcf7 thunde Mon, 6 Mar 2017 21:46:42 +0100 Fixed Windows compile of VOIP + dc65d3f Phenom Sun, 5 Mar 2017 13:22:30 +0100 Fix Setting list width. + 0316c8c thunde Mon, 6 Mar 2017 06:34:06 +0100 Added workaround for crash on Windows 7 for Qt versions with gcc 5.3.0. The call to GetProcAddress in openssl (cryptlib.c) finds an function pointer to the not existing function _OPENSSL_isservice in the executable running on Windows 7. + 313e1b3 csoler Sun, 5 Mar 2017 20:08:53 +0100 updated translation files + 88a5c03 csoler Sun, 5 Mar 2017 20:08:36 +0100 removed some debug info + 94c9c94 thunde Sun, 5 Mar 2017 14:30:45 +0100 updated version number to 0.6.2 in rsversion.in + b71f475 csoler Sun, 5 Mar 2017 14:14:46 +0100 qick fix to allow re-advertising for known forums/channels during the same session. Will be reset at restart (probably best) + fbd72dd csoler Sun, 5 Mar 2017 13:57:49 +0100 fixed settings SoundPage + 15bb0ff felisu Sun, 5 Mar 2017 02:45:37 +0100 Update ChatPage.h + 951820f felisu Sun, 5 Mar 2017 02:45:07 +0100 Update ForumPage.h + 63174aa felisu Sun, 5 Mar 2017 02:44:18 +0100 Update PostedPage.h + ca75515 felisu Sun, 5 Mar 2017 02:43:40 +0100 Update MessagePage.h + d3cdd15 csoler Sat, 4 Mar 2017 21:20:34 +0100 fixed uninitialised memory read in GxsReputation + dec5c5c csoler Sat, 4 Mar 2017 21:13:34 +0100 suppressed uninitialised memory leak in LocalDirectoryStorage + b14e4d5 csoler Sat, 4 Mar 2017 21:08:10 +0100 removed memory leak due to missing delete for BWGraph + 0bd0056 csoler Sat, 4 Mar 2017 20:52:41 +0100 fixed memory leak in RsGxsNetService + 7111579 csoler Sat, 4 Mar 2017 20:52:06 +0100 fixed memory leak in config of msgService + 2302c46 csoler Sat, 4 Mar 2017 16:41:10 +0100 updated version number in changelog + 0024ddf csoler Sat, 4 Mar 2017 16:39:39 +0100 fixed utf8 bug in ShareManager + 3600905 csoler Sat, 4 Mar 2017 12:04:41 +0100 updated packaging files + c715b03 csoler Sat, 4 Mar 2017 11:56:51 +0100 updated version number to 0.6.2 + 5e2a253 csoler Sat, 4 Mar 2017 11:44:31 +0100 updated ubuntu changelog + bd8189c csoler Tue, 28 Feb 2017 18:05:44 +0100 added test to prevent msgs with a different name to be used as different version + 763f227 csoler Sun, 26 Feb 2017 20:39:40 +0100 merged upstream/master into v0.6-EditPosts branch + 22f2edb csoler Sat, 11 Feb 2017 10:45:30 +0100 removed debug info and added comment + ea82d26 csoler Thu, 9 Feb 2017 23:35:59 +0100 fixed signature verification bug for versionned messages + 5bf8376 csoler Thu, 9 Feb 2017 21:49:24 +0100 fixed a few more bugs in post version UI + 8deeec6 csoler Thu, 9 Feb 2017 18:45:55 +0100 fixed UI for post versions + b93130a csoler Thu, 9 Feb 2017 16:15:35 +0100 fixed a few bugs in post version collecting + f8056e5 csoler Thu, 9 Feb 2017 14:49:43 +0100 added collection of older posts versions. + 6681985 csoler Wed, 8 Feb 2017 20:40:47 +0100 merged upstream/master + dfcb66d csoler Fri, 3 Feb 2017 13:02:53 +0100 added spinbox to show older versions + 777a73e csoler Fri, 3 Feb 2017 12:48:51 +0100 added GUI for editing forum messages + + -- Retroshare Dev Team Dim, 23 Apr 2017 16:00:00 +0100 + +retroshare06 (0.6.2-1.931442~trusty) trusty; urgency=low + 931442a csoler Sat, 4 Mar 2017 00:07:51 +0100 fixed compilation b4e0a8f csoler Sat, 4 Mar 2017 00:04:52 +0100 removed unused file DirectoriesPage.{cpp,ui,h} e257563 csoler Sat, 4 Mar 2017 00:01:21 +0100 merged Directories settings page into Transfers and renamed it Files From 06e90e65494d096b8fbe760b6cc1e62935b0cb8d Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 23 Apr 2017 17:49:07 +0200 Subject: [PATCH 23/39] added control file for zesty --- build_scripts/Debian+Ubuntu/control.zesty | 44 +++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 build_scripts/Debian+Ubuntu/control.zesty diff --git a/build_scripts/Debian+Ubuntu/control.zesty b/build_scripts/Debian+Ubuntu/control.zesty new file mode 100644 index 000000000..9b557e3b8 --- /dev/null +++ b/build_scripts/Debian+Ubuntu/control.zesty @@ -0,0 +1,44 @@ +Source: retroshare06 +Section: devel +Priority: standard +Maintainer: Cyril Soler +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 +Standards-Version: 3.9.6 +Homepage: http://retroshare.sourceforge.net + +Package: retroshare06-voip-plugin +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, retroshare06, libspeex1, libspeexdsp1, libqt5multimedia5 +Description: RetroShare VOIP plugin + This package provides a plugin for RetroShare, a secured Friend-to-Friend communication + plateform. The plugin adds voice-over-IP functionality to the private chat window. Both + friends chatting together need the plugin installed to be able to talk together. + +Package: retroshare06-feedreader-plugin +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, retroshare06 +Description: RetroShare FeedReader plugin + This package provides a plugin for RetroShare, a secured Friend-to-Friend communication + plateform. The plugin adds a RSS feed reader tab to retroshare. + +Package: retroshare06-nogui +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, gnome-keyring +Conflicts: retroshare06 +Description: Secure communication with friends + This is the command-line client for RetroShare network. This client + can be contacted and talked-to using SSL. Clients exist for portable + devices running e.g. Android. + +Package: retroshare06 +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, gnome-keyring +Conflicts: retroshare06-nogui +Description: Secure communication with friends + RetroShare is a Open Source cross-platform, private and secure decentralised + commmunication platform. It lets you to securely chat and share files with your + friends and family, using a web-of-trust to authenticate peers and OpenSSL to + encrypt all communication. RetroShare provides filesharing, chat, messages, + forums and channels. + + From 190a638cc1076674d53d1d64dc2fef29fd28b125 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 23 Apr 2017 17:53:25 +0200 Subject: [PATCH 24/39] added zesty to ubuntu releases --- build_scripts/Debian+Ubuntu/makeSourcePackage.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_scripts/Debian+Ubuntu/makeSourcePackage.sh b/build_scripts/Debian+Ubuntu/makeSourcePackage.sh index 2e6f4305a..dc5892b07 100755 --- a/build_scripts/Debian+Ubuntu/makeSourcePackage.sh +++ b/build_scripts/Debian+Ubuntu/makeSourcePackage.sh @@ -54,7 +54,7 @@ while [ ${#} -gt 0 ]; do done if test "${dist}" = "" ; then - dist="precise trusty vivid xenial yakkety" + dist="precise trusty vivid xenial yakkety zesty" fi echo Attempting to get revision number... From 6313d89718cffa5133b32034b170078992af350b Mon Sep 17 00:00:00 2001 From: defnax Date: Mon, 24 Apr 2017 01:23:05 +0200 Subject: [PATCH 25/39] Improved look n feel of Profile Generation Window. --- retroshare-gui/src/gui/GenCertDialog.cpp | 40 +- retroshare-gui/src/gui/GenCertDialog.ui | 1160 ++++++-------- retroshare-gui/src/gui/images.qrc | 1331 +++++++++-------- retroshare-gui/src/gui/images/cancel.png | Bin 792 -> 640 bytes .../src/gui/images/logo/logo_spash2.png | Bin 0 -> 102946 bytes 5 files changed, 1177 insertions(+), 1354 deletions(-) create mode 100644 retroshare-gui/src/gui/images/logo/logo_spash2.png diff --git a/retroshare-gui/src/gui/GenCertDialog.cpp b/retroshare-gui/src/gui/GenCertDialog.cpp index ff8fbf909..c65c08b89 100644 --- a/retroshare-gui/src/gui/GenCertDialog.cpp +++ b/retroshare-gui/src/gui/GenCertDialog.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -45,7 +46,7 @@ #include #define IMAGE_GOOD ":/images/accepted16.png" -#define IMAGE_BAD ":/images/deletemail24.png" +#define IMAGE_BAD ":/images/cancel.png" class EntropyCollectorWidget: public QTextBrowser { @@ -133,8 +134,8 @@ GenCertDialog::GenCertDialog(bool onlyGenerateIdentity, QWidget *parent) //ui.headerFrame->setHeaderImage(QPixmap(":/icons/svg/profile.svg")); //ui.headerFrame->setHeaderText(tr("Create a new profile")); - connect(ui.reuse_existing_node_CB, SIGNAL(clicked()), this, SLOT(switchReuseExistingNode())); - connect(ui.adv_checkbox, SIGNAL(clicked()), this, SLOT(setupState())); + connect(ui.reuse_existing_node_CB, SIGNAL(triggered()), this, SLOT(switchReuseExistingNode())); + connect(ui.adv_checkbox, SIGNAL(triggered()), this, SLOT(setupState())); connect(ui.nodeType_CB, SIGNAL(currentIndexChanged(int)), this, SLOT(setupState())); connect(ui.genButton, SIGNAL(clicked()), this, SLOT(genPerson())); @@ -172,6 +173,11 @@ GenCertDialog::GenCertDialog(bool onlyGenerateIdentity, QWidget *parent) /* get all available pgp private certificates.... * mark last one as default. */ + + QMenu *menu = new QMenu(tr("Advanced options")); + menu->addAction(ui.adv_checkbox); + menu->addAction(ui.reuse_existing_node_CB); + ui.optionsButton->setMenu(menu); mAllFieldsOk = false ; mEntropyOk = false ; @@ -246,22 +252,22 @@ void GenCertDialog::setupState() genNewGPGKey = generate_new; - ui.no_node_label->setVisible(false); + //ui.no_node_label->setVisible(false); setWindowTitle(generate_new?tr("Create new profile and new Retroshare node"):tr("Create new Retroshare node")); //ui.headerFrame->setHeaderText(generate_new?tr("Create a new profile and node"):tr("Create a new node")); ui.label_nodeType->setVisible(adv_state) ; ui.nodeType_CB->setVisible(adv_state) ; - ui.reuse_existing_node_CB->setVisible(adv_state) ; + ui.reuse_existing_node_CB->setEnabled(adv_state) ; ui.importIdentity_PB->setVisible(adv_state && !generate_new) ; ui.exportIdentity_PB->setVisible(adv_state && !generate_new) ; ui.genPGPuser->setVisible(adv_state && haveGPGKeys && !generate_new) ; - ui.genprofileinfo_label->setVisible(false); - ui.no_gpg_key_label->setText(tr("Welcome to Retroshare. Before you can proceed you need to create a profile and associate a node with it. To do so please fill out this form.\nAlternatively you can import a (previously exported) profile. Just uncheck \"Create a new profile\"")); - ui.no_gpg_key_label->setVisible(false); + //ui.genprofileinfo_label->setVisible(false); + //ui.no_gpg_key_label->setText(tr("Welcome to Retroshare. Before you can proceed you need to create a profile and associate a node with it. To do so please fill out this form.\nAlternatively you can import a (previously exported) profile. Just uncheck \"Create a new profile\"")); + //no_gpg_key_label->setVisible(false); ui.nickname_label->setVisible(adv_state) ; ui.nickname_input->setVisible(adv_state) ; @@ -269,7 +275,7 @@ void GenCertDialog::setupState() ui.name_label->setVisible(true); ui.name_input->setVisible(generate_new); - ui.header_label->setVisible(false) ; + //ui.header_label->setVisible(false) ; ui.nickname_label->setVisible(adv_state && !mOnlyGenerateIdentity); ui.nickname_input->setVisible(adv_state && !mOnlyGenerateIdentity); @@ -300,14 +306,16 @@ void GenCertDialog::setupState() if(mEntropyOk && mAllFieldsOk) { ui.genButton->setEnabled(true) ; - ui.genButton->setIcon(QIcon(IMAGE_GOOD)) ; + //ui.genButton->setIcon(QIcon(IMAGE_GOOD)) ; ui.genButton->setToolTip(tr("Click to create your node and/or profile")) ; + ui.generate_label->setPixmap(QPixmap(IMAGE_GOOD)) ; } else { ui.genButton->setEnabled(false) ; - ui.genButton->setIcon(QIcon(IMAGE_BAD)) ; + //ui.genButton->setIcon(QIcon(IMAGE_BAD)) ; ui.genButton->setToolTip(tr("Disabled until all fields correctly set and enough randomness collected.")) ; + ui.generate_label->setPixmap(QPixmap(IMAGE_BAD)) ; } } @@ -495,9 +503,9 @@ void GenCertDialog::genPerson() } //generate a new gpg key std::string err_string; - ui.no_gpg_key_label->setText(tr("Generating new node key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. \n\nFill in your password when asked, to sign your new key.")); - ui.no_gpg_key_label->show(); - ui.reuse_existing_node_CB->hide(); + //_key_label->setText(tr("Generating new node key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. \n\nFill in your password when asked, to sign your new key.")); + //ui.no_gpg_key_label->show(); + //ui.reuse_existing_node_CB->hide(); ui.name_label->hide(); ui.name_input->hide(); ui.nickname_label->hide(); @@ -514,9 +522,9 @@ void GenCertDialog::genPerson() ui.node_input->hide(); ui.genButton->hide(); ui.importIdentity_PB->hide(); - ui.genprofileinfo_label->hide(); + //ui.genprofileinfo_label->hide(); ui.nodeType_CB->hide(); - ui.adv_checkbox->hide(); + //ui.adv_checkbox->hide(); ui.keylength_label->hide(); ui.keylength_comboBox->hide(); diff --git a/retroshare-gui/src/gui/GenCertDialog.ui b/retroshare-gui/src/gui/GenCertDialog.ui index 8325ffa3a..468c17693 100644 --- a/retroshare-gui/src/gui/GenCertDialog.ui +++ b/retroshare-gui/src/gui/GenCertDialog.ui @@ -6,8 +6,8 @@ 0 0 - 724 - 667 + 533 + 544 @@ -54,7 +54,10 @@ - :/images/logo/logo_splash.png + :/images/logo/logo_spash2.png + + + false Qt::AlignCenter @@ -77,22 +80,13 @@ - - - - 16777215 - 32 - - - - <html><head/><body><p>Use this if you need to import an existing profile, if you want to generate a new node with an already existing key, or if you want to create a TOR/I2P hidden node.</p></body></html> - + - Advanced options + Options - :/icons/settings/general.svg:/icons/settings/general.svg + :/icons/svg/options.svg:/icons/svg/options.svg @@ -100,667 +94,481 @@ 24 - + false + + true + - - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 178 - - - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 178 - - - - - - - - - 255 - 255 - 178 - - - - - - - 255 - 255 - 178 - - - - - - - - true + + + - QFrame::Box + QFrame::StyledPanel - - You can create a new profile with this form. -Alternatively you can use an existing profile. Just uncheck "Create a new profile" - - - true + + QFrame::Raised + + + + + + + + + + + + + + PGP key length + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> + + + + + + 1024 + + + QLineEdit::Password + + + + + + + This password is for PGP + + + Password + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + + + + This password is for PGP + + + Password (check) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> + + + 24 + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + + + + + Standard node + + + + + TOR/I2P Hidden node + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> + + + 64 + + + + + + + Node name + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 32 + + + + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> + + + + + + 64 + + + + + + + + 0 + 0 + + + + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. + + + + + + + + + + + 0 + 0 + + + + Export this profle + + + + + + + + 0 + 0 + + + + Import profile + + + + + + + + + + + + + + + + + 0 + 0 + + + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> + + + + + + 1024 + + + QLineEdit::Password + + + + + + + Profile name + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Randomness + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Node type + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + hidden address + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 6 + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 32 + + + + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> + + + 64 + + + + + + + Port + + + + + + + + 0 + 0 + + + + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> + + + 1 + + + 65535 + + + 7812 + + + + + + + + + + + + Chat identity + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 12 + + + + + + + Go! + + + + 16 + 16 + + + + + + + + + + + + + + - - - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 178 - - - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 178 - - - - - - - - - 255 - 255 - 178 - - - - - - - 255 - 255 - 178 - - - - - - - - true - - - QFrame::Box - - - You can create and run Retroshare nodes on different computers using the same profile. To do so just export the selected profile, import it on the other computer and create a new node with it. - - - true - - - - - - - It looks like no profile (PGP keys) exists. Please fill in the form below to create one, or import an existing profile. - - - true - - - - - - - No node exists for this profile. - - - true - - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> - - - - - - 1024 - - - QLineEdit::Password - - - - - - - This password is for PGP - - - Password - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - - - - This password is for PGP - - - Password (check) - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - - - 0 - 0 - - - - <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> - - - 24 - - - - - - - - - - - - - - - - - - - - - - 0 - 0 - - - - - Standard node - - - - - TOR/I2P Hidden node - - - - - - - - PGP key length - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> - - - 64 - - - - - - - Node name - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 32 - - - - <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> - - - - - - 64 - - - - - - - - 0 - 0 - - - - Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. - - - - - - - - 0 - 0 - - - - Export this profle - - - - - - - - 0 - 0 - - - - Import profile - - - - - - - - 0 - 0 - - - - Re-use an existing profile - - - - - - - - - - - - - - - - - 0 - 0 - - - - <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> - - - - - - 1024 - - - QLineEdit::Password - - - - - - - Profile name - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Randomness - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Node type - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - hidden address - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 6 - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 32 - - - - <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> - - - 64 - - - - - - - Port - - - - - - - - 0 - 0 - - - - <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> - - - 1 - - - 65535 - - - 7812 - - - - - - - - - - - - Chat identity - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - - - - Go! - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - @@ -778,27 +586,33 @@ Alternatively you can use an existing profile. Just uncheck "Create a new p + + + true + + + Advanced options + + + + + true + + + Use existing node + + - - - StyledLabel - QLabel -

gui/common/StyledLabel.h
- - name_input node_input password_input password_input_2 - adv_checkbox keylength_comboBox exportIdentity_PB - reuse_existing_node_CB genPGPuser hiddenaddr_input hiddenport_spinBox - genButton importIdentity_PB diff --git a/retroshare-gui/src/gui/images.qrc b/retroshare-gui/src/gui/images.qrc index adad4c232..fbdb66d3d 100644 --- a/retroshare-gui/src/gui/images.qrc +++ b/retroshare-gui/src/gui/images.qrc @@ -1,667 +1,668 @@ - - images/network_map.png - images/global_switch_on.png - images/global_switch_off.png - images/switch00.png - images/switch01.png - images/switch10.png - images/switch11.png - images/add_chat24.png - images/RSS_004_32.png - images/mail-encrypted-full.png - images/mail-signed-full.png - images/document-edit-sign.png - images/decrypt-mail.png - images/inbox_22.png - images/blue_lock.png - images/blue_lock_open.png - images/d-chat64.png - images/edit_24.png - images/streaming.png - images/white-bubble-64.png - images/orange-bubble-64.png - images/stock_signature_bad.png - images/stock_signature_ok.png - images/stock_signature_missing.png - images/stock_signature_unverified.png - images/anonymous_128_blue.png - images/browsable_128_green.png - images/browsable_128_blue.png - images/blank_128_green.png - images/blank_128_blue.png - images/door_in.png - images/tor-logo.png - images/help/addafriend.png - images/help/addfriendkey.png - images/help/dhtgreen.png - icons/help_64.png - images/help/natgreen.png - images/help/natred.png - images/attach.png - images/pgp.png - images/rs_wizard.png - images/avatar_request.png - images/avatar_refused.png - images/avatar_request_unknown.png - images/backblue.png - images/backchat.png - images/buttonframe.png - images/btn1.png - images/btn2.png - images/btn3.png - images/btn4.png - images/btn_26.png - images/btn_26_hover.png - images/btn_26_pressed.png - images/btn_27.png - images/btn_27_hover.png - images/btn_blue.png - images/btn_blue_hover.png - images/btn_green.png - images/btn_green_hover.png - images/btn_green_pressed.png - images/connect_creating.png - images/dht16.png - images/dht32.png - images/edit-clear-history.png - images/edit_16.png - images/feedback_arrow.png - images/feedback_arrow_hover.png - images/firewall_24.png - images/list_bullet_arrow.png - images/rc_combined.png - images/combobox_arrow.png - images/arrow-left.png - images/arrow-right.png - help/authors.html - help/licence.html - help/thanks.html - images/accepted16.png - images/add_image24.png - images/add_channel64.png - images/add_channel24.png - images/add_channel32.png - images/admin-16.png - images/admin-32.png - images/admin-24.png - images/admin-48.png - images/user/add_group22.png - images/user/add_group256.png - images/user/edit_group64.png - images/avatarstatus-bg-116.png - images/avatarstatus-bg-online-116.png - images/avatarstatus-bg-idle-116.png - images/avatarstatus-bg-away-116.png - images/avatarstatus-bg-busy-116.png - images/avatarstatus-bg-offline-116.png - images/avatarstatus-bg-70.png - images/avatarstatus-bg-online-70.png - images/avatarstatus-bg-idle-70.png - images/avatarstatus-bg-away-70.png - images/avatarstatus-bg-busy-70.png - images/avatarstatus-bg-offline-70.png - images/browse-looking.gif - images/back.png - images/backgroundl.png - images/blockdevice.png - images/blockdevice2.png - images/configure.png - images/channels.png - images/turtle.png - images/channels16.png - images/channels24.png - images/channels32.png - images/channels_new.png - images/channelsred.png - images/channelsyellow.png - images/channelsgreen.png - images/channelsblue.png - images/copyrslink.png - images/contacts24.png - images/contactsclosed24.png - images/connection.png - images/contact_new.png - images/contact_new22.png - images/contact.png - images/contact22.png - images/Client0.png - images/Client1.png - images/Client2.png - images/Client3.png - images/Client4.png - images/closenormal.png - images/closehover.png - images/closepressed.png - images/denied16.png - images/filetype-association.png - images/FileTypeAny.png - images/FileTypeArchive.png - images/FileTypeAudio.png - images/FileTypeCDImage.png - images/FileTypeDocument.png - images/FileTypePicture.png - images/FileTypeProgram.png - images/FileTypeVideo.png - images/fonts.png - images/folder16.png - images/foldermail.png - images/folderopen.png - images/fileopen.png - images/graph-downloaded.png - images/graph-downloading.png - images/graph-notdownload.png - images/graph-checking.png - images/graph-blue.png - images/add-share24.png - images/add_24x24.png - images/advsearch_24x24.png - images/amsn16.png - images/attachment.png - images/avatar_background.png - images/backgroundimage.png - images/button_cancel.png - images/calendar.png - images/chat.png - images/chat_22.png - images/chat_24.png - images/chat_32.png - images/chat_64.png - images/chat_x24.png - images/chat_red24.png - images/cancel.png - images/close-down.png - images/close_normal.png - images/console-small-down.png - images/console-small-hover.png - images/console-small-up.png - images/contact_new128.png - images/copy.png - images/delete.png - images/deleteall.png - images/deletemail-pressed.png - images/deletemail24.png - images/directoryadd_24x24_shadow.png - images/directoryremove_24x24_shadow.png - images/directoryselect_24x24_shadow.png - images/diskSave.png - images/document_save.png - images/down.png - images/down_24x24.png - images/download.png - images/download16.png - images/edit_add24.png - images/edit-bold.png - images/edit-italic.png - images/edit-underline.png - images/edit_remove24.png - images/encrypted16.png - images/encrypted22.png - images/encrypted32.png - images/encrypted48.png - images/disabled_plugin_48.png - images/evolution.png - images/exit_24x24.png - images/exit_32.png - images/expand_frame.png - images/exportpeers_16x16.png - images/extension_32.png - images/filefind.png - images/fileinfo.png - images/filename.png - images/filepriority.png - images/filecomments.png - images/filerating0.png - images/filerating1.png - images/filerating2.png - images/filerating3.png - images/filerating4.png - images/filerating5.png - images/fileshare16.png - images/fileshare24.png - images/fileshare32.png - images/fileshare48.png - images/fileshare64.png - images/find.png - images/find-16.png - images/emoticons/kopete/kopete020.png - images/flags/af.png - images/flags/bg.png - images/flags/zh_CN.png - images/flags/zh_TW.png - images/flags/ca_ES.png - images/flags/cs.png - images/flags/de.png - images/flags/da.png - images/flags/el.png - images/flags/en.png - images/flags/es.png - images/flags/fi.png - images/flags/fr.png - images/flags/hu.png - images/flags/it.png - images/flags/ja_JP.png - images/flags/ko.png - images/flags/nl.png - images/flags/pl.png - images/flags/pt.png - images/flags/ru.png - images/flags/sv.png - images/flags/sl.png - images/flags/tr.png - images/folder-draft.png - images/folder-draft24-pressed.png - images/folder-draft24.png - images/folder_inbox64.png - images/folder-inbox.png - images/folder-inbox-new.png - images/folder-outbox.png - images/folder-sent.png - images/folder-trash.png - images/folder_doments.png - images/folder_green.png - images/folder_red.png - images/folder_grey.png - images/folder_yellow.png - images/folder_open.png - images/folder_video.png - images/folder_blueshared.png - images/forward.png - images/friendsfolder24.png - images/kgames.png - images/go-down.png - images/go-top.png - images/go-up.png - images/go-bottom.png - images/graph-area.png - images/graph-line.png - images/groupchat.png - images/genbackground.png - images/gohome.png - images/gpgp_key_generate.png - images/help.png - images/help24.png - images/hide_toolbox_frame.png - images/hide_frame.png - images/highlight.png - images/hi16-app-ktorrent.png - images/hi24-app-ktorrent.png - images/hot_0.png - images/hot_1.png - images/hot_2.png - images/hot_3.png - images/hot_4.png - images/hot_5.png - images/image16.png - images/imageblocked_24.png - images/info16.png - images/im-user.png - images/im-user-offline.png - images/im-user-away.png - images/im-user-busy.png - images/im-user-inactive.png - images/informations_24x24.png - images/connect_friend.png - images/kalarm.png - images/kbackgammon.png - images/kblogger.png - images/hi48-app-kblogger.png - images/hi64-app-kblogger.png - images/transfers_new.png - images/kcmsystem24.png - images/kdmconfig.png - images/konsole.png - images/newsfeed128.png - images/newsfeed128_notify.png - images/konversation.png - images/konversation16.png - images/konversation128.png - images/konv_message2.png - images/konv_message3.png - images/konv_message64.png - images/konversation64.png - images/forums_new.png - images/ksysguard.png - images/ksysguard32.png - images/ktorrent.png - images/ktorrent32.png - images/knewsticker24.png - images/library.png - images/loadcert16.png - images/ledoff1.png - images/ledon1.png - images/locale.png - images/looknfeel.png - images/lphoto.png - images/lphoto16.png - images/lphoto24.png - images/logo/logo_16.png - images/logo/logo_24.png - images/logo/logo_24_0.png - images/logo/logo_24_1.png - images/logo/logo_24_2.png - images/logo/logo_32.png - images/logo/logo_48.png - images/logo/logo_64.png - images/logo/logo_128.png - images/logo/logo_256.png - images/logo/logo_512.png - images/logo/logo_info.png - images/logo/logo_splash.png - images/logobar/logo_bar_fill.png - images/logobar/logo_bar_start.png - images/logobar/rslogo.png - images/logobar/rslogo2.png - images/mail-message-new.png - images/mail-signed.png - images/mail-signature-unknown.png - images/mail_delete.png - images/mail_get.png - images/mail_reply.png - images/mail_replyall.png - images/mail_forward.png - images/mail_send.png - images/mail_new.png - images/mail_send24.png - images/mailforward24-hover.png - images/message-mail.png - images/message-mail-read.png - images/message-mail-imapdelete.png - images/message-mail-replied-read.png - images/message-mail-forwarded-read.png - images/message-mail-replied.png - images/message-mail-forwarded.png - images/message-mail-replied-forw.png - images/message-mail-replied-forw-read.png - images/message-state-read.png - images/message-state-unread.png - images/message-state-header.png - images/message-state-new.png - images/message-news.png - images/message_new.png - images/message.png - images/messenger.png - images/mute-off-16.png - images/mute-on-16.png - images/my_documents_16.png - images/my_documents_22.png - images/network.png - images/network16.png - images/network32.png - images/new-mail-alert.png - images/new_forum16.png - images/newmsg.png - images/no_avatar_70.png - images/no_avatar_background.png - images/openimage.png - images/office-chart-area-stacked.png - images/office-chart-line.png - images/pasterslink.png - images/package_games1.png - images/pin32.png - images/print24.png - images/priorityauto.png - images/priorityhigh.png - images/prioritylow.png - images/prioritynormal.png - images/pause.png - images/preview.png - images/player_play.png - images/quick_restart24.png - images/quote_24.png - images/redled.png - images/greenled.png - images/grayled.png - images/yellowled.png - images/rate-1.png - images/rate-2.png - images/rate-3.png - images/rate-4.png - images/rate-5.png - images/rating.png - images/records.png - images/replymail-pressed.png - images/replymail24.png - images/replymailall24-hover.png - images/reset.png - images/resume.png - images/security-high-16.png - images/security-high-48.png - images/security-low-48.png - images/security-medium-48.png - images/security-high-off-48.png - images/security-low-off-48.png - images/security-medium-off-48.png - images/save24.png - images/send24.png - images/settings.png - images/settings16.png - images/show_toolbox_frame.png - images/start.png - images/stop.png - images/star-on-16.png - images/star-off-16.png - images/StatsCumulative.png - images/StatisticsDetail.png - images/status_unknown.png - images/startall.png - images/server_24x24.png - images/sort_incr.png - images/sort_decrease.png - images/sound.png - images/tab-dock.png - images/tab-undock.png - images/tab-new.png - images/tag24.png - images/transferupdown.png - images/tools_wizard.png - images/typing.png - images/trustsettings.png - images/uploads.png - images/headerFrame.png - images/loader/indicator-16.gif - images/loader/indicator-32.gif - images/loader/circleball-16.gif - images/loader/progress.gif - images/mimetypes/pdf.png - images/mimetypes/rscollection-16.png - images/mimetypes/patch.png - images/mimetypes/source_c.png - images/mimetypes/source_cpp.png - images/mimetypes/source_h.png - images/view-certificate-copy-32.png - images/view-certificate-export-32.png - images/textedit/textbold.png - images/textedit/textitalic.png - images/textedit/textunder.png - images/textedit/textjustify.png - images/textedit/textcenter.png - images/textedit/textleft.png - images/textedit/textright.png - images/textedit/editcopy.png - images/textedit/editcut.png - images/textedit/editpaste.png - images/textedit/editredo.png - images/textedit/editundo.png - images/textedit/exportpdf.png - images/textedit/filenew.png - images/textedit/fileopen.png - images/textedit/fileprint.png - images/textedit/filesave.png - images/textedit/format-text-color.png - images/textedit/format-list-ordered.png - images/textedit/format-list-unordered.png - images/textedit/zoomin.png - images/textedit/zoomout.png - images/textedit/format_font_size_more.png - images/textedit/format_font_size_less.png - images/textedit/hi22-action-format-text-blockquote.png - images/textedit/hi22-action-format-text-code.png - images/textedit/hi22-action-insert-more-mark.png - images/toaster/chat.png - images/toaster/hangup.png - images/toaster/pickup.png - images/toaster/backgroundtoaster.png - images/thumb-default-video.png - images/user/add_user24.png - images/user/add_user48.png - images/user/remove_user24.png - images/user/deny_user48.png - images/user/friends24.png - images/user/friends32.png - images/user/friends64.png - images/user/friends24_notify.png - images/user/friend_suggestion16.png - images/user/identity16.png - images/user/identity24.png - images/user/identity24_low.png - images/user/identity32.png - images/user/identity48.png - images/user/identityinfo48.png - images/user/identityinfo64.png - images/user/identityoffline24.png - images/user/identity24away.png - images/user/identity24busy.png - images/user/identity24idle.png - images/user/identityavaiblecyan24.png - images/user/invite24.png - images/user/agt_forum24.png - images/user/agt_forum32.png - images/user/identitygray16.png - images/user/add_user16.png - images/user/personal64.png - images/user/personal128.png - images/user/kuser24.png - images/user/agt_forum64.png - images/user/agt_forum128.png - images/user/group16.png - images/user/group24.png - images/user/servicepermissions64.png - images/user/user_request16.png - images/user/user_request48.png - images/user/user_request_unknown48.png - images/up.png - images/up0down0.png - images/up0down1.png - images/up1down1.png - images/up1down0.png - images/underconstruction.png - images/user.png - images/view-certificate-sign-32.png - images/view_calendar_day.png - images/view_calendar_week.png - images/view_calendar_month.png - images/view_calendar_list.png - images/view_split_top_bottom.png - images/vote_up.png - images/vote_down.png - images/vote_neutral.png - images/window_fullscreen.png - images/window_nofullscreen.png - images/identity/identities_32.png - images/identity/identity_64.png - images/identity/identity_create_32.png - images/identity/identity_create_64.png - images/identity/identity_delete_32.png - images/identity/identity_edit_32.png - images/identity/identity_edit_64.png - qss/chat/standard/private/info.xml - qss/chat/standard/private/incoming.htm - qss/chat/standard/private/outgoing.htm - qss/chat/standard/private/hincoming.htm - qss/chat/standard/private/houtgoing.htm - qss/chat/standard/private/ooutgoing.htm - qss/chat/standard/private/system.htm - qss/chat/standard/private/main.css - qss/chat/standard/private/variants/Standard.css - qss/chat/standard/public/info.xml - qss/chat/standard/public/incoming.htm - qss/chat/standard/public/outgoing.htm - qss/chat/standard/public/hincoming.htm - qss/chat/standard/public/houtgoing.htm - qss/chat/standard/public/ooutgoing.htm - qss/chat/standard/public/system.htm - qss/chat/standard/public/main.css - qss/chat/standard/public/variants/Standard.css - qss/chat/standard/history/info.xml - qss/chat/standard/history/incoming.htm - qss/chat/standard/history/outgoing.htm - qss/chat/standard/history/hincoming.htm - qss/chat/standard/history/houtgoing.htm - qss/chat/standard/history/ooutgoing.htm - qss/chat/standard/history/system.htm - qss/chat/standard/history/main.css - qss/chat/standard/history/variants/Standard.css - qss/chat/compact/private/info.xml - qss/chat/compact/private/incoming.htm - qss/chat/compact/private/outgoing.htm - qss/chat/compact/private/hincoming.htm - qss/chat/compact/private/houtgoing.htm - qss/chat/compact/private/ooutgoing.htm - qss/chat/compact/private/system.htm - qss/chat/compact/private/main.css - qss/chat/compact/private/variants/Standard.css - qss/chat/compact/private/variants/Colored.css - qss/chat/compact/public/info.xml - qss/chat/compact/public/incoming.htm - qss/chat/compact/public/outgoing.htm - qss/chat/compact/public/hincoming.htm - qss/chat/compact/public/houtgoing.htm - qss/chat/compact/public/ooutgoing.htm - qss/chat/compact/public/system.htm - qss/chat/compact/public/main.css - qss/chat/compact/public/variants/Standard.css - qss/chat/compact/public/variants/Colored.css - qss/chat/compact/history/info.xml - qss/chat/compact/history/incoming.htm - qss/chat/compact/history/outgoing.htm - qss/chat/compact/history/hincoming.htm - qss/chat/compact/history/houtgoing.htm - qss/chat/compact/history/ooutgoing.htm - qss/chat/compact/history/system.htm - qss/chat/compact/history/main.css - qss/chat/compact/history/variants/Standard.css - qss/chat/compact/history/variants/Colored.css - qss/stylesheet/qss.default - qss/stylesheet/Standard.qss - images/connect/connectFriendWatermark.png - images/connect/connectFriendLogo.png - images/connect/connectFriendBanner.png - images/connect/connectFriendBanner1.png - images/connect/info16.png - images/connect/mail_send.png - images/tags/pgp-known.png - images/tags/pgp-unknown.png - images/tags/anon.png - images/tags/dev-ambassador.png - images/tags/dev-translator.png - images/tags/dev-patcher.png - images/tags/developer.png - images/circles/circles_32.png - images/circles/circles_64.png - images/newsfeed/news-feed-32.png - images/newsfeed/news-feed-notify-32.png - images/share-icon-16.png - help/version.html - images/view-certificate-sign-48.png - images/toasterEnable.png - images/toasterDisable.png - images/library_edit.png - images/library_view.png - images/library_add.png - images/library64.png - images/library16.png - images/btn_red_pressed.png - images/btn_red_hover.png - images/btn_red.png - images/view-feeds.png - images/view-files.png - images/emblem-web.png - images/rsmessenger16.png - images/rsmessenger32.png - images/rsmessenger48.png - images/SmileyText.png - images/SimpleText.png - images/ColoredText.png - + + images/logo/logo_spash2.png + images/network_map.png + images/global_switch_on.png + images/global_switch_off.png + images/switch00.png + images/switch01.png + images/switch10.png + images/switch11.png + images/add_chat24.png + images/RSS_004_32.png + images/mail-encrypted-full.png + images/mail-signed-full.png + images/document-edit-sign.png + images/decrypt-mail.png + images/inbox_22.png + images/blue_lock.png + images/blue_lock_open.png + images/d-chat64.png + images/edit_24.png + images/streaming.png + images/white-bubble-64.png + images/orange-bubble-64.png + images/stock_signature_bad.png + images/stock_signature_ok.png + images/stock_signature_missing.png + images/stock_signature_unverified.png + images/anonymous_128_blue.png + images/browsable_128_green.png + images/browsable_128_blue.png + images/blank_128_green.png + images/blank_128_blue.png + images/door_in.png + images/tor-logo.png + images/help/addafriend.png + images/help/addfriendkey.png + images/help/dhtgreen.png + icons/help_64.png + images/help/natgreen.png + images/help/natred.png + images/attach.png + images/pgp.png + images/rs_wizard.png + images/avatar_request.png + images/avatar_refused.png + images/avatar_request_unknown.png + images/backblue.png + images/backchat.png + images/buttonframe.png + images/btn1.png + images/btn2.png + images/btn3.png + images/btn4.png + images/btn_26.png + images/btn_26_hover.png + images/btn_26_pressed.png + images/btn_27.png + images/btn_27_hover.png + images/btn_blue.png + images/btn_blue_hover.png + images/btn_green.png + images/btn_green_hover.png + images/btn_green_pressed.png + images/connect_creating.png + images/dht16.png + images/dht32.png + images/edit-clear-history.png + images/edit_16.png + images/feedback_arrow.png + images/feedback_arrow_hover.png + images/firewall_24.png + images/list_bullet_arrow.png + images/rc_combined.png + images/combobox_arrow.png + images/arrow-left.png + images/arrow-right.png + help/authors.html + help/licence.html + help/thanks.html + images/accepted16.png + images/add_image24.png + images/add_channel64.png + images/add_channel24.png + images/add_channel32.png + images/admin-16.png + images/admin-32.png + images/admin-24.png + images/admin-48.png + images/user/add_group22.png + images/user/add_group256.png + images/user/edit_group64.png + images/avatarstatus-bg-116.png + images/avatarstatus-bg-online-116.png + images/avatarstatus-bg-idle-116.png + images/avatarstatus-bg-away-116.png + images/avatarstatus-bg-busy-116.png + images/avatarstatus-bg-offline-116.png + images/avatarstatus-bg-70.png + images/avatarstatus-bg-online-70.png + images/avatarstatus-bg-idle-70.png + images/avatarstatus-bg-away-70.png + images/avatarstatus-bg-busy-70.png + images/avatarstatus-bg-offline-70.png + images/browse-looking.gif + images/back.png + images/backgroundl.png + images/blockdevice.png + images/blockdevice2.png + images/configure.png + images/channels.png + images/turtle.png + images/channels16.png + images/channels24.png + images/channels32.png + images/channels_new.png + images/channelsred.png + images/channelsyellow.png + images/channelsgreen.png + images/channelsblue.png + images/copyrslink.png + images/contacts24.png + images/contactsclosed24.png + images/connection.png + images/contact_new.png + images/contact_new22.png + images/contact.png + images/contact22.png + images/Client0.png + images/Client1.png + images/Client2.png + images/Client3.png + images/Client4.png + images/closenormal.png + images/closehover.png + images/closepressed.png + images/denied16.png + images/filetype-association.png + images/FileTypeAny.png + images/FileTypeArchive.png + images/FileTypeAudio.png + images/FileTypeCDImage.png + images/FileTypeDocument.png + images/FileTypePicture.png + images/FileTypeProgram.png + images/FileTypeVideo.png + images/fonts.png + images/folder16.png + images/foldermail.png + images/folderopen.png + images/fileopen.png + images/graph-downloaded.png + images/graph-downloading.png + images/graph-notdownload.png + images/graph-checking.png + images/graph-blue.png + images/add-share24.png + images/add_24x24.png + images/advsearch_24x24.png + images/amsn16.png + images/attachment.png + images/avatar_background.png + images/backgroundimage.png + images/button_cancel.png + images/calendar.png + images/chat.png + images/chat_22.png + images/chat_24.png + images/chat_32.png + images/chat_64.png + images/chat_x24.png + images/chat_red24.png + images/cancel.png + images/close-down.png + images/close_normal.png + images/console-small-down.png + images/console-small-hover.png + images/console-small-up.png + images/contact_new128.png + images/copy.png + images/delete.png + images/deleteall.png + images/deletemail-pressed.png + images/deletemail24.png + images/directoryadd_24x24_shadow.png + images/directoryremove_24x24_shadow.png + images/directoryselect_24x24_shadow.png + images/diskSave.png + images/document_save.png + images/down.png + images/down_24x24.png + images/download.png + images/download16.png + images/edit_add24.png + images/edit-bold.png + images/edit-italic.png + images/edit-underline.png + images/edit_remove24.png + images/encrypted16.png + images/encrypted22.png + images/encrypted32.png + images/encrypted48.png + images/disabled_plugin_48.png + images/evolution.png + images/exit_24x24.png + images/exit_32.png + images/expand_frame.png + images/exportpeers_16x16.png + images/extension_32.png + images/filefind.png + images/fileinfo.png + images/filename.png + images/filepriority.png + images/filecomments.png + images/filerating0.png + images/filerating1.png + images/filerating2.png + images/filerating3.png + images/filerating4.png + images/filerating5.png + images/fileshare16.png + images/fileshare24.png + images/fileshare32.png + images/fileshare48.png + images/fileshare64.png + images/find.png + images/find-16.png + images/emoticons/kopete/kopete020.png + images/flags/af.png + images/flags/bg.png + images/flags/zh_CN.png + images/flags/zh_TW.png + images/flags/ca_ES.png + images/flags/cs.png + images/flags/de.png + images/flags/da.png + images/flags/el.png + images/flags/en.png + images/flags/es.png + images/flags/fi.png + images/flags/fr.png + images/flags/hu.png + images/flags/it.png + images/flags/ja_JP.png + images/flags/ko.png + images/flags/nl.png + images/flags/pl.png + images/flags/pt.png + images/flags/ru.png + images/flags/sv.png + images/flags/sl.png + images/flags/tr.png + images/folder-draft.png + images/folder-draft24-pressed.png + images/folder-draft24.png + images/folder_inbox64.png + images/folder-inbox.png + images/folder-inbox-new.png + images/folder-outbox.png + images/folder-sent.png + images/folder-trash.png + images/folder_doments.png + images/folder_green.png + images/folder_red.png + images/folder_grey.png + images/folder_yellow.png + images/folder_open.png + images/folder_video.png + images/folder_blueshared.png + images/forward.png + images/friendsfolder24.png + images/kgames.png + images/go-down.png + images/go-top.png + images/go-up.png + images/go-bottom.png + images/graph-area.png + images/graph-line.png + images/groupchat.png + images/genbackground.png + images/gohome.png + images/gpgp_key_generate.png + images/help.png + images/help24.png + images/hide_toolbox_frame.png + images/hide_frame.png + images/highlight.png + images/hi16-app-ktorrent.png + images/hi24-app-ktorrent.png + images/hot_0.png + images/hot_1.png + images/hot_2.png + images/hot_3.png + images/hot_4.png + images/hot_5.png + images/image16.png + images/imageblocked_24.png + images/info16.png + images/im-user.png + images/im-user-offline.png + images/im-user-away.png + images/im-user-busy.png + images/im-user-inactive.png + images/informations_24x24.png + images/connect_friend.png + images/kalarm.png + images/kbackgammon.png + images/kblogger.png + images/hi48-app-kblogger.png + images/hi64-app-kblogger.png + images/transfers_new.png + images/kcmsystem24.png + images/kdmconfig.png + images/konsole.png + images/newsfeed128.png + images/newsfeed128_notify.png + images/konversation.png + images/konversation16.png + images/konversation128.png + images/konv_message2.png + images/konv_message3.png + images/konv_message64.png + images/konversation64.png + images/forums_new.png + images/ksysguard.png + images/ksysguard32.png + images/ktorrent.png + images/ktorrent32.png + images/knewsticker24.png + images/library.png + images/loadcert16.png + images/ledoff1.png + images/ledon1.png + images/locale.png + images/looknfeel.png + images/lphoto.png + images/lphoto16.png + images/lphoto24.png + images/logo/logo_16.png + images/logo/logo_24.png + images/logo/logo_24_0.png + images/logo/logo_24_1.png + images/logo/logo_24_2.png + images/logo/logo_32.png + images/logo/logo_48.png + images/logo/logo_64.png + images/logo/logo_128.png + images/logo/logo_256.png + images/logo/logo_512.png + images/logo/logo_info.png + images/logo/logo_splash.png + images/logobar/logo_bar_fill.png + images/logobar/logo_bar_start.png + images/logobar/rslogo.png + images/logobar/rslogo2.png + images/mail-message-new.png + images/mail-signed.png + images/mail-signature-unknown.png + images/mail_delete.png + images/mail_get.png + images/mail_reply.png + images/mail_replyall.png + images/mail_forward.png + images/mail_send.png + images/mail_new.png + images/mail_send24.png + images/mailforward24-hover.png + images/message-mail.png + images/message-mail-read.png + images/message-mail-imapdelete.png + images/message-mail-replied-read.png + images/message-mail-forwarded-read.png + images/message-mail-replied.png + images/message-mail-forwarded.png + images/message-mail-replied-forw.png + images/message-mail-replied-forw-read.png + images/message-state-read.png + images/message-state-unread.png + images/message-state-header.png + images/message-state-new.png + images/message-news.png + images/message_new.png + images/message.png + images/messenger.png + images/mute-off-16.png + images/mute-on-16.png + images/my_documents_16.png + images/my_documents_22.png + images/network.png + images/network16.png + images/network32.png + images/new-mail-alert.png + images/new_forum16.png + images/newmsg.png + images/no_avatar_70.png + images/no_avatar_background.png + images/openimage.png + images/office-chart-area-stacked.png + images/office-chart-line.png + images/pasterslink.png + images/package_games1.png + images/pin32.png + images/print24.png + images/priorityauto.png + images/priorityhigh.png + images/prioritylow.png + images/prioritynormal.png + images/pause.png + images/preview.png + images/player_play.png + images/quick_restart24.png + images/quote_24.png + images/redled.png + images/greenled.png + images/grayled.png + images/yellowled.png + images/rate-1.png + images/rate-2.png + images/rate-3.png + images/rate-4.png + images/rate-5.png + images/rating.png + images/records.png + images/replymail-pressed.png + images/replymail24.png + images/replymailall24-hover.png + images/reset.png + images/resume.png + images/security-high-16.png + images/security-high-48.png + images/security-low-48.png + images/security-medium-48.png + images/security-high-off-48.png + images/security-low-off-48.png + images/security-medium-off-48.png + images/save24.png + images/send24.png + images/settings.png + images/settings16.png + images/show_toolbox_frame.png + images/start.png + images/stop.png + images/star-on-16.png + images/star-off-16.png + images/StatsCumulative.png + images/StatisticsDetail.png + images/status_unknown.png + images/startall.png + images/server_24x24.png + images/sort_incr.png + images/sort_decrease.png + images/sound.png + images/tab-dock.png + images/tab-undock.png + images/tab-new.png + images/tag24.png + images/transferupdown.png + images/tools_wizard.png + images/typing.png + images/trustsettings.png + images/uploads.png + images/headerFrame.png + images/loader/indicator-16.gif + images/loader/indicator-32.gif + images/loader/circleball-16.gif + images/loader/progress.gif + images/mimetypes/pdf.png + images/mimetypes/rscollection-16.png + images/mimetypes/patch.png + images/mimetypes/source_c.png + images/mimetypes/source_cpp.png + images/mimetypes/source_h.png + images/view-certificate-copy-32.png + images/view-certificate-export-32.png + images/textedit/textbold.png + images/textedit/textitalic.png + images/textedit/textunder.png + images/textedit/textjustify.png + images/textedit/textcenter.png + images/textedit/textleft.png + images/textedit/textright.png + images/textedit/editcopy.png + images/textedit/editcut.png + images/textedit/editpaste.png + images/textedit/editredo.png + images/textedit/editundo.png + images/textedit/exportpdf.png + images/textedit/filenew.png + images/textedit/fileopen.png + images/textedit/fileprint.png + images/textedit/filesave.png + images/textedit/format-text-color.png + images/textedit/format-list-ordered.png + images/textedit/format-list-unordered.png + images/textedit/zoomin.png + images/textedit/zoomout.png + images/textedit/format_font_size_more.png + images/textedit/format_font_size_less.png + images/textedit/hi22-action-format-text-blockquote.png + images/textedit/hi22-action-format-text-code.png + images/textedit/hi22-action-insert-more-mark.png + images/toaster/chat.png + images/toaster/hangup.png + images/toaster/pickup.png + images/toaster/backgroundtoaster.png + images/thumb-default-video.png + images/user/add_user24.png + images/user/add_user48.png + images/user/remove_user24.png + images/user/deny_user48.png + images/user/friends24.png + images/user/friends32.png + images/user/friends64.png + images/user/friends24_notify.png + images/user/friend_suggestion16.png + images/user/identity16.png + images/user/identity24.png + images/user/identity24_low.png + images/user/identity32.png + images/user/identity48.png + images/user/identityinfo48.png + images/user/identityinfo64.png + images/user/identityoffline24.png + images/user/identity24away.png + images/user/identity24busy.png + images/user/identity24idle.png + images/user/identityavaiblecyan24.png + images/user/invite24.png + images/user/agt_forum24.png + images/user/agt_forum32.png + images/user/identitygray16.png + images/user/add_user16.png + images/user/personal64.png + images/user/personal128.png + images/user/kuser24.png + images/user/agt_forum64.png + images/user/agt_forum128.png + images/user/group16.png + images/user/group24.png + images/user/servicepermissions64.png + images/user/user_request16.png + images/user/user_request48.png + images/user/user_request_unknown48.png + images/up.png + images/up0down0.png + images/up0down1.png + images/up1down1.png + images/up1down0.png + images/underconstruction.png + images/user.png + images/view-certificate-sign-32.png + images/view_calendar_day.png + images/view_calendar_week.png + images/view_calendar_month.png + images/view_calendar_list.png + images/view_split_top_bottom.png + images/vote_up.png + images/vote_down.png + images/vote_neutral.png + images/window_fullscreen.png + images/window_nofullscreen.png + images/identity/identities_32.png + images/identity/identity_64.png + images/identity/identity_create_32.png + images/identity/identity_create_64.png + images/identity/identity_delete_32.png + images/identity/identity_edit_32.png + images/identity/identity_edit_64.png + qss/chat/standard/private/info.xml + qss/chat/standard/private/incoming.htm + qss/chat/standard/private/outgoing.htm + qss/chat/standard/private/hincoming.htm + qss/chat/standard/private/houtgoing.htm + qss/chat/standard/private/ooutgoing.htm + qss/chat/standard/private/system.htm + qss/chat/standard/private/main.css + qss/chat/standard/private/variants/Standard.css + qss/chat/standard/public/info.xml + qss/chat/standard/public/incoming.htm + qss/chat/standard/public/outgoing.htm + qss/chat/standard/public/hincoming.htm + qss/chat/standard/public/houtgoing.htm + qss/chat/standard/public/ooutgoing.htm + qss/chat/standard/public/system.htm + qss/chat/standard/public/main.css + qss/chat/standard/public/variants/Standard.css + qss/chat/standard/history/info.xml + qss/chat/standard/history/incoming.htm + qss/chat/standard/history/outgoing.htm + qss/chat/standard/history/hincoming.htm + qss/chat/standard/history/houtgoing.htm + qss/chat/standard/history/ooutgoing.htm + qss/chat/standard/history/system.htm + qss/chat/standard/history/main.css + qss/chat/standard/history/variants/Standard.css + qss/chat/compact/private/info.xml + qss/chat/compact/private/incoming.htm + qss/chat/compact/private/outgoing.htm + qss/chat/compact/private/hincoming.htm + qss/chat/compact/private/houtgoing.htm + qss/chat/compact/private/ooutgoing.htm + qss/chat/compact/private/system.htm + qss/chat/compact/private/main.css + qss/chat/compact/private/variants/Standard.css + qss/chat/compact/private/variants/Colored.css + qss/chat/compact/public/info.xml + qss/chat/compact/public/incoming.htm + qss/chat/compact/public/outgoing.htm + qss/chat/compact/public/hincoming.htm + qss/chat/compact/public/houtgoing.htm + qss/chat/compact/public/ooutgoing.htm + qss/chat/compact/public/system.htm + qss/chat/compact/public/main.css + qss/chat/compact/public/variants/Standard.css + qss/chat/compact/public/variants/Colored.css + qss/chat/compact/history/info.xml + qss/chat/compact/history/incoming.htm + qss/chat/compact/history/outgoing.htm + qss/chat/compact/history/hincoming.htm + qss/chat/compact/history/houtgoing.htm + qss/chat/compact/history/ooutgoing.htm + qss/chat/compact/history/system.htm + qss/chat/compact/history/main.css + qss/chat/compact/history/variants/Standard.css + qss/chat/compact/history/variants/Colored.css + qss/stylesheet/qss.default + qss/stylesheet/Standard.qss + images/connect/connectFriendWatermark.png + images/connect/connectFriendLogo.png + images/connect/connectFriendBanner.png + images/connect/connectFriendBanner1.png + images/connect/info16.png + images/connect/mail_send.png + images/tags/pgp-known.png + images/tags/pgp-unknown.png + images/tags/anon.png + images/tags/dev-ambassador.png + images/tags/dev-translator.png + images/tags/dev-patcher.png + images/tags/developer.png + images/circles/circles_32.png + images/circles/circles_64.png + images/newsfeed/news-feed-32.png + images/newsfeed/news-feed-notify-32.png + images/share-icon-16.png + help/version.html + images/view-certificate-sign-48.png + images/toasterEnable.png + images/toasterDisable.png + images/library_edit.png + images/library_view.png + images/library_add.png + images/library64.png + images/library16.png + images/btn_red_pressed.png + images/btn_red_hover.png + images/btn_red.png + images/view-feeds.png + images/view-files.png + images/emblem-web.png + images/rsmessenger16.png + images/rsmessenger32.png + images/rsmessenger48.png + images/SmileyText.png + images/SimpleText.png + images/ColoredText.png + diff --git a/retroshare-gui/src/gui/images/cancel.png b/retroshare-gui/src/gui/images/cancel.png index e2db55f22d6752e10a57f07e286081ebebacfea5..87cd0b0125d6193c16c59f25b88396493e885f6b 100644 GIT binary patch delta 626 zcmbQi*1$SJvYwfNfk8u;KNv_c7dv@|aBy(ke(3)I$mJ~Xh%9DcVB8JDj8<>t*I;7bhncr0V4trO$q6BL!3~9^ez=`v3p`1_p)|3=C@- z7}^;ax)>NHGBC_wV3@RV8~-&$Yo&2VqjRrz%Wf)yIxML zNk#fnMd@KL&yxwUbLD0Bn`j+%w_hSJyhL7fiK5gJWx1ttLd)a?R;!4wSC`&wsJ2;K zexH~9VK0XhKF+7Yd>WJ$8%}w#rhL&r(*XwlRuSl!;c9-pjzSkAY#orE&d1 zL9Ro_#)o`84qI6rwKO^=#B*GT=cJw8X&3v`eqLwX+%7OMToB^992RytJmhj}!j+`B zYYDN}lM`kPYraQ8tFbY(tBE5_$)W~Sy}1J-p=iu=wVMs0a*6lae66V1{}lBO?zm@bvWb^7ao147zar?!70^UVZxV z^%o5M27y07@b~ZEfB&xL-Ae)*Fx%6`F+@VL_n@m-69WV50e+1eN@eBcN$g4G&;OoZ z_@U%HkI2G1Y&DW|L{gS~pLvn#*O$}oPDyv;)@d%@S+MWUnh6;~!r6rr_0J!v3}TiP zmj2Sd_M*wT2km`jv);P39Gh=-=K8Ceh+g@r^*SZhhb$H}`H087pLX?B)^^UB3LD?w z|E_d;s@(f#UZF$9XErfRx31(k!O_kdKc~AvNZxs~aQ62tX(>Q=GI+ZBxvXf delta 780 zcmV+n1M~cV1(*hq8Gi-<001BJ|6u?C0^dnQK~y-6rIF8XlLZ{cKi{`M*KTWR*LIyV zOM#7*DZ@=SF_3}AQA3P|gNg^^%|8H7{u4T5;)N3sh*3r~9Q0sBM3RX=h7k4($wr!W zUAMOD_O^Z7zVFuqJ$Uy?p2Kr^o;=A%RF(fDF~ob^L^ zH>W3RaM#t*fdMUmmp>n$oF`v` z);GWW<6T{X8-LfagArUWy~x7#3tYQ*U;M!9W0N|Xd56Y>dw6NVP@4PMEslKs#fSj7 z!@bq{RDZ|F(lUi+9ee>|JyA+;y-hurBRMxmp;CdWNzChEEgUAbv5jI00Q-_DfCrBw zQLTgC1pOJbJebx(GO4#fZ-Z7r7eRrwu3!}WegvSSe}9l#c7+(s&31K8ly~>o09XWHdDZnkp~*aF;j$D!ITe-Q6e zE5FW)!hazk*1n$uij^G>npNJ9C-le7yZ~4zM$>Ll2lrGks74{jp2A_CIxsel|JX5} z2U0-MZqivSF%=DI4FWAkF`A7=^pj6NYj&F^B~=F6D9{fS zS`9+mJA8chU9+i9A9v2Y$E}`j{TuWVs0Df@9)HuU&%OLZD8P+yfK`v{&nt;uZGk=p zUFr_%@5x@B5y5a!R7AFc1H);q4G;5bq430pAqPQ4uwiVfm|y%Vo*5 zPy`#n2ALh&&$;PS*vf#Tineh%3bv!^vqJ-Xn?8sGq9QmV{0nAcK6qK?z8e4l002ov KP6b4+LSTX`Yi$Pr diff --git a/retroshare-gui/src/gui/images/logo/logo_spash2.png b/retroshare-gui/src/gui/images/logo/logo_spash2.png new file mode 100644 index 0000000000000000000000000000000000000000..dab5aa9381d067df268a5f8fac5d2811c40d0dbe GIT binary patch literal 102946 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 z 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�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

pLiP5elc| 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 Date: Mon, 24 Apr 2017 16:00:23 +0200 Subject: [PATCH 26/39] Changed: difference time to absolute time. --- libresapi/src/api/IdentityHandler.cpp | 5 ++--- libresapi/src/api/PeersHandler.cpp | 4 +--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/libresapi/src/api/IdentityHandler.cpp b/libresapi/src/api/IdentityHandler.cpp index 1306f9a54..be2e28622 100644 --- a/libresapi/src/api/IdentityHandler.cpp +++ b/libresapi/src/api/IdentityHandler.cpp @@ -418,8 +418,7 @@ void IdentityHandler::handleGetIdentityDetails(Request& req, Response& resp) } resp.mDataStream << makeKeyValue("pgp_name", pgp_name); - time_t now = time(NULL); - resp.mDataStream << makeKeyValue("last_usage", difftime(now, data.mLastUsageTS)); + resp.mDataStream << makeKeyValue("last_usage", (uint32_t)data.mLastUsageTS); bool isAnonymous = false; if(!data.mPgpKnown) @@ -475,7 +474,7 @@ void IdentityHandler::handleGetIdentityDetails(Request& req, Response& resp) for(std::map::const_iterator it(details.mUseCases.begin()); it != details.mUseCases.end(); ++it) { usagesStream.getStreamToMember() - << makeKeyValue("usage_time", difftime(now, data.mLastUsageTS)) + << makeKeyValue("usage_time", (uint32_t)data.mLastUsageTS) << makeKeyValue("usage_service", (int)(it->first.mServiceId)) << makeKeyValue("usage_case", (int)(it->first.mUsageCode)); } diff --git a/libresapi/src/api/PeersHandler.cpp b/libresapi/src/api/PeersHandler.cpp index dd03f8351..6649acdcb 100644 --- a/libresapi/src/api/PeersHandler.cpp +++ b/libresapi/src/api/PeersHandler.cpp @@ -7,7 +7,6 @@ #include #include -#include #include "Operators.h" #include "ApiTypes.h" @@ -746,12 +745,11 @@ void PeersHandler::handleGetNodeOptions(Request& req, Response& resp) return; } - time_t now = time(NULL); resp.mDataStream << makeKeyValue("peer_id", detail.id.toStdString()); resp.mDataStream << makeKeyValue("name", detail.name); resp.mDataStream << makeKeyValue("location", detail.location); resp.mDataStream << makeKeyValue("pgp_id", detail.gpg_id.toStdString()); - resp.mDataStream << makeKeyValue("last_contact", difftime(now, detail.lastConnect)); + resp.mDataStream << makeKeyValue("last_contact", detail.lastConnect); std::string status_message = mRsMsgs->getCustomStateString(detail.id); resp.mDataStream << makeKeyValueReference("status_message", status_message); From 13275820961a0509a38bc4e028f3bdb5b44041ca Mon Sep 17 00:00:00 2001 From: Phenom Date: Mon, 24 Apr 2017 17:28:25 +0200 Subject: [PATCH 27/39] Fix Relay setting values Was multiply by 1024 then divide by 1000. --- retroshare-gui/src/gui/settings/RelayPage.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/retroshare-gui/src/gui/settings/RelayPage.cpp b/retroshare-gui/src/gui/settings/RelayPage.cpp index 3124f40db..d26550c8b 100644 --- a/retroshare-gui/src/gui/settings/RelayPage.cpp +++ b/retroshare-gui/src/gui/settings/RelayPage.cpp @@ -129,15 +129,15 @@ void RelayPage::load() uint32_t bandwidth; rsDht->getRelayAllowance(RSDHT_RELAY_CLASS_FRIENDS, count, bandwidth); whileBlocking(ui.noFriendSpinBox)->setValue(count); - whileBlocking(ui.bandFriendSpinBox)->setValue(bandwidth / 1000); + whileBlocking(ui.bandFriendSpinBox)->setValue(bandwidth / 1024); rsDht->getRelayAllowance(RSDHT_RELAY_CLASS_FOF, count, bandwidth); whileBlocking(ui.noFOFSpinBox)->setValue(count); - whileBlocking(ui.bandFOFSpinBox)->setValue(bandwidth / 1000); + whileBlocking(ui.bandFOFSpinBox)->setValue(bandwidth / 1024); rsDht->getRelayAllowance(RSDHT_RELAY_CLASS_GENERAL, count, bandwidth); whileBlocking(ui.noGeneralSpinBox)->setValue(count); - whileBlocking(ui.bandGeneralSpinBox)->setValue(bandwidth / 1000); + whileBlocking(ui.bandGeneralSpinBox)->setValue(bandwidth / 1024); updateTotals(); From 6e42cf420015a84d45b22050b1ff2dc76abd85a6 Mon Sep 17 00:00:00 2001 From: Phenom Date: Tue, 18 Apr 2017 11:56:25 +0200 Subject: [PATCH 28/39] Fix Clang warnings: field 'mPassword' will be initialized after field 'mPrevIsBad' warning: field 'mPassword' will be initialized after field 'mPrevIsBad' [-Wreorder] --- libresapi/src/api/RsControlModule.cpp | 4 ++-- libresapi/src/api/RsControlModule.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libresapi/src/api/RsControlModule.cpp b/libresapi/src/api/RsControlModule.cpp index cb3cdcdf2..ece94b7af 100644 --- a/libresapi/src/api/RsControlModule.cpp +++ b/libresapi/src/api/RsControlModule.cpp @@ -25,8 +25,8 @@ RsControlModule::RsControlModule(int argc, char **argv, StateTokenServer* sts, A mRunState(WAITING_INIT), mAutoLoginNextTime(false), mWantPassword(false), - mPassword(""), - mPrevIsBad(false) + mPrevIsBad(false), + mPassword("") { mStateToken = sts->getNewToken(); this->argc = argc; diff --git a/libresapi/src/api/RsControlModule.h b/libresapi/src/api/RsControlModule.h index 7e306405c..8b8b1f3f0 100644 --- a/libresapi/src/api/RsControlModule.h +++ b/libresapi/src/api/RsControlModule.h @@ -77,7 +77,7 @@ private: // to notify that a password callback is waiting // to answer the request, clear the flag and set the password bool mWantPassword; - bool mPrevIsBad; + bool mPrevIsBad ; std::string mTitle; std::string mKeyName; std::string mPassword; From 490f8d2f5462b3b4dc639b975a752703077566a3 Mon Sep 17 00:00:00 2001 From: Phenom Date: Tue, 18 Apr 2017 12:00:00 +0200 Subject: [PATCH 29/39] Fix Clang warnings: 'TYPE_IDENTITY' not handled warning: enumeration value 'TYPE_IDENTITY' not handled in switch [- Wswitch] --- retroshare-gui/src/util/HandleRichText.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/retroshare-gui/src/util/HandleRichText.cpp b/retroshare-gui/src/util/HandleRichText.cpp index 73801bd5b..c5f578d3a 100644 --- a/retroshare-gui/src/util/HandleRichText.cpp +++ b/retroshare-gui/src/util/HandleRichText.cpp @@ -230,12 +230,13 @@ bool RsHtml::canReplaceAnchor(QDomDocument &/*doc*/, QDomElement &/*element*/, c case RetroShareLink::TYPE_PERSON: case RetroShareLink::TYPE_FORUM: case RetroShareLink::TYPE_CHANNEL: - case RetroShareLink::TYPE_POSTED: case RetroShareLink::TYPE_SEARCH: case RetroShareLink::TYPE_MESSAGE: case RetroShareLink::TYPE_EXTRAFILE: case RetroShareLink::TYPE_PRIVATE_CHAT: case RetroShareLink::TYPE_PUBLIC_MSG: + case RetroShareLink::TYPE_POSTED: + case RetroShareLink::TYPE_IDENTITY: // not yet implemented break; From f22dc0f0df195524590edc378395130b7d712c8f Mon Sep 17 00:00:00 2001 From: Phenom Date: Tue, 18 Apr 2017 12:02:34 +0200 Subject: [PATCH 30/39] Fix Clang warnings: unused variable 'action' warning: unused variable 'action' [-Wunused-variable] QAction *action = contextMenu- >addAction(QIcon(":/images/chat_24.png"),tr("Copy identity to clipboard"),this,SLOT(copyRetroshareLink())) ; --- retroshare-gui/src/gui/Identity/IdDialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/retroshare-gui/src/gui/Identity/IdDialog.cpp b/retroshare-gui/src/gui/Identity/IdDialog.cpp index aac7e3ba5..755dab9c9 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.cpp +++ b/retroshare-gui/src/gui/Identity/IdDialog.cpp @@ -2408,8 +2408,8 @@ void IdDialog::IdListCustomPopupMenu( QPoint ) } } - if(n_selected_items==1) - QAction *action = contextMenu->addAction(QIcon(":/images/chat_24.png"),tr("Copy identity to clipboard"),this,SLOT(copyRetroshareLink())) ; + if (n_selected_items==1) + 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())); From ff1908eda6293d5105fbe1d60d5c41641e1bb0e8 Mon Sep 17 00:00:00 2001 From: Phenom Date: Wed, 19 Apr 2017 11:50:24 +0200 Subject: [PATCH 31/39] Fix Clang Static Analyser: Undefined allocation of 0 bytes Unix API: Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131): Call to 'malloc' has an allocation size of 0 bytes 1: Loop body executed 0 times in /home/phenom/GIT/RetroShare/trunk/ libbitdht/src/util/bdbloom.cc:223 2: Calling 'bloomFilter::getFilter' in /home/phenom/GIT/RetroShare/ trunk/libbitdht/src/util/bdbloom.cc:240 3: 'bytes' initialized to 0 in /home/phenom/GIT/RetroShare/trunk/ libbitdht/src/util/bdbloom.cc:141 4: Call to 'malloc' has an allocation size of 0 bytes in /home/phenom/ GIT/RetroShare/trunk/libbitdht/src/util/bdbloom.cc:148 --- libbitdht/src/util/bdbloom.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libbitdht/src/util/bdbloom.cc b/libbitdht/src/util/bdbloom.cc index 36f3a3bee..016808ea4 100644 --- a/libbitdht/src/util/bdbloom.cc +++ b/libbitdht/src/util/bdbloom.cc @@ -144,6 +144,11 @@ std::string bloomFilter::getFilter() bytes++; } + if (bytes==0) + { + std::cerr << "(EE) Error. Cannot allocate memory for 0 byte in " << __PRETTY_FUNCTION__ << std::endl; + return std::string(); + } // convert to binary array. uint8_t *tmparray = (uint8_t *) malloc(bytes); From b2b7d004cd4204c3ae06f1876329dd4800f38f98 Mon Sep 17 00:00:00 2001 From: Phenom Date: Wed, 19 Apr 2017 14:01:35 +0200 Subject: [PATCH 32/39] Fix CSA warnings: Called C++ object pointer is null Logic error: Called C++ object pointer is null 1: 'di' initialized here in /home/phenom/GIT/RetroShare/trunk/plugins/ VOIP/gui/VOIPGUIHandler.cpp:157 2: Assuming 'di' is null in /home/phenom/GIT/RetroShare/trunk/plugins/ VOIP/gui/VOIPGUIHandler.cpp:158 3: Called C++ object pointer is null in /home/phenom/GIT/RetroShare/ trunk/plugins/VOIP/gui/VOIPGUIHandler.cpp:161 --- plugins/VOIP/gui/VOIPGUIHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/VOIP/gui/VOIPGUIHandler.cpp b/plugins/VOIP/gui/VOIPGUIHandler.cpp index 6a7d7d703..f999ed437 100644 --- a/plugins/VOIP/gui/VOIPGUIHandler.cpp +++ b/plugins/VOIP/gui/VOIPGUIHandler.cpp @@ -155,7 +155,7 @@ void VOIPGUIHandler::ReceivedVoipBandwidthInfo(const RsPeerId &peer_id, int byte #endif ChatDialog *di = ChatDialog::getExistingChat(ChatId(peer_id)) ; - if(!di) + if(di) { ChatWidget *cw = di->getChatWidget(); From 90cd6233d8b3e446984ddc1b68b2e89fbf35995d Mon Sep 17 00:00:00 2001 From: Phenom Date: Wed, 19 Apr 2017 14:04:50 +0200 Subject: [PATCH 33/39] Fix CAS warnings: Potential leak of memory pointed to by 'toaster' Memory Error: Memory leak: Potential leak of memory pointed to by 'toaster' 1: Memory is allocated in /home/phenom/GIT/RetroShare/trunk/plugins/ VOIP/gui/VOIPToasterNotify.cpp:182 --- plugins/VOIP/gui/VOIPToasterNotify.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/VOIP/gui/VOIPToasterNotify.cpp b/plugins/VOIP/gui/VOIPToasterNotify.cpp index d2de3f6bd..eff862467 100644 --- a/plugins/VOIP/gui/VOIPToasterNotify.cpp +++ b/plugins/VOIP/gui/VOIPToasterNotify.cpp @@ -180,7 +180,7 @@ ToasterItem* VOIPToasterNotify::testToasterItem(QString tag) if (tag == "Invitation") toaster = new ToasterItem(new VOIPToasterItem(ownId, tr("Test VOIP Invitation"), VOIPToasterItem::Invitation)); #endif if (tag == "AudioCall") toaster = new ToasterItem(new VOIPToasterItem(ownId, tr("Test VOIP Audio Call"), VOIPToasterItem::AudioCall)); - if (tag == "VideoCall") toaster = new ToasterItem(new VOIPToasterItem(ownId, tr("Test VOIP Video Call"), VOIPToasterItem::VideoCall)); + if (tag == "VideoCall" || toaster == NULL) toaster = new ToasterItem(new VOIPToasterItem(ownId, tr("Test VOIP Video Call"), VOIPToasterItem::VideoCall)); return toaster; } From 30632dcfeb5a065caee5b3b9d610ad50880a65b2 Mon Sep 17 00:00:00 2001 From: Phenom Date: Wed, 19 Apr 2017 14:06:56 +0200 Subject: [PATCH 34/39] Fix CSA warnings: Called C++ object pointer is null Logic error: Called C++ object pointer is null 1: Calling 'MainWindow::createNotifyIcons' in /home/phenom/GIT/ RetroShare/trunk/retroshare-gui/src/gui/MainWindow.cpp:291 2: Loop body executed 0 times in /home/phenom/GIT/RetroShare/trunk/ retroshare-gui/src/gui/MainWindow.cpp:600 3: Calling 'MainWindow::updateTrayCombine' in /home/phenom/GIT/ RetroShare/trunk/retroshare-gui/src/gui/MainWindow.cpp:605 4: Value assigned to field 'notifyMenu' in /home/phenom/GIT/RetroShare/ trunk/retroshare-gui/src/gui/MainWindow.cpp:654 5: Assuming pointer value is null in /home/phenom/GIT/RetroShare/trunk/ retroshare-gui/src/gui/MainWindow.cpp:658 6: Called C++ object pointer is null in /home/phenom/GIT/RetroShare/ trunk/retroshare-gui/src/gui/MainWindow.cpp:679 --- retroshare-gui/src/gui/MainWindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/retroshare-gui/src/gui/MainWindow.cpp b/retroshare-gui/src/gui/MainWindow.cpp index 8e8534345..af2e10574 100644 --- a/retroshare-gui/src/gui/MainWindow.cpp +++ b/retroshare-gui/src/gui/MainWindow.cpp @@ -676,7 +676,8 @@ void MainWindow::updateTrayCombine() } } - notifyMenu->menuAction()->setVisible(visible); + if (notifyMenu) + notifyMenu->menuAction()->setVisible(visible); // update tray icon updateFriends(); From 1f16f46aad3769457561e5a5d0d26fef81beec3c Mon Sep 17 00:00:00 2001 From: Phenom Date: Wed, 19 Apr 2017 14:15:34 +0200 Subject: [PATCH 35/39] Fix CSA warnings: Called C++ object pointer is null Logic error: Called C++ object pointer is null 1: Assuming pointer value is null in /home/phenom/GIT/RetroShare/trunk/ retroshare-gui/src/gui/common/MimeTextEdit.cpp:65 2: Called C++ object pointer is null in /home/phenom/GIT/RetroShare/ trunk/retroshare-gui/src/gui/common/MimeTextEdit.cpp:83 --- retroshare-gui/src/gui/common/MimeTextEdit.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/retroshare-gui/src/gui/common/MimeTextEdit.cpp b/retroshare-gui/src/gui/common/MimeTextEdit.cpp index 5ff657ce3..9c0395ffb 100644 --- a/retroshare-gui/src/gui/common/MimeTextEdit.cpp +++ b/retroshare-gui/src/gui/common/MimeTextEdit.cpp @@ -77,6 +77,7 @@ void MimeTextEdit::insertFromMimeData(const QMimeData* source) } } #endif + if (source == NULL) return; //insert retroshare links QList links; From 90aaace69c9a74509ed11992226c5c0d4c9dbcd6 Mon Sep 17 00:00:00 2001 From: Phenom Date: Wed, 19 Apr 2017 14:18:35 +0200 Subject: [PATCH 36/39] Fix CSA warnings: Called C++ object pointer is null Logic error: Called C++ object pointer is null 1: Value assigned to field 'mMainAction' in /home/phenom/GIT/ RetroShare/trunk/retroshare-gui/src/gui/common/UserNotify.cpp:94 2: Assuming pointer value is null in /home/phenom/GIT/RetroShare/trunk/ retroshare-gui/src/gui/common/UserNotify.cpp:95 3: Called C++ object pointer is null in /home/phenom/GIT/RetroShare/ trunk/retroshare-gui/src/gui/common/UserNotify.cpp:103 --- retroshare-gui/src/gui/common/UserNotify.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/retroshare-gui/src/gui/common/UserNotify.cpp b/retroshare-gui/src/gui/common/UserNotify.cpp index 96cbf554b..6c70b3c9f 100644 --- a/retroshare-gui/src/gui/common/UserNotify.cpp +++ b/retroshare-gui/src/gui/common/UserNotify.cpp @@ -99,7 +99,7 @@ void UserNotify::initialize(QToolBar *mainToolBar, QAction *mainAction, QListWid } } mListItem = listItem; - if (mListItem && !mMainAction) { + if (mListItem && mMainAction) { mButtonText = mMainAction->text(); } } From 593c0cb7e65b13a2e07d74fdc15d563e93f78e75 Mon Sep 17 00:00:00 2001 From: Phenom Date: Wed, 19 Apr 2017 14:19:54 +0200 Subject: [PATCH 37/39] Fix CSA warnings: Called C++ object pointer is null Logic error: Called C++ object pointer is null 1: Null pointer value stored to field 'mInternalTokenQueue' in /home/ phenom/GIT/RetroShare/trunk/retroshare-gui/src/gui/gxs/ GxsGroupDialog.cpp:70 2: Calling 'GxsGroupDialog::init' in /home/phenom/GIT/RetroShare/trunk/ retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp:72 3: Calling 'GxsGroupDialog::initMode' in /home/phenom/GIT/RetroShare/ trunk/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp:136 4: Calling 'GxsGroupDialog::requestGroup' in /home/phenom/GIT/ RetroShare/trunk/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp:190 5: Called C++ object pointer is null in /home/phenom/GIT/RetroShare/ trunk/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp:866 --- retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp b/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp index b18ab3688..cd792623d 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp +++ b/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp @@ -863,7 +863,8 @@ void GxsGroupDialog::requestGroup(const RsGxsGroupId &groupId) std::cerr << std::endl; uint32_t token; - mInternalTokenQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds, GXSGROUP_INTERNAL_LOADGROUP); + if (mInternalTokenQueue) + mInternalTokenQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds, GXSGROUP_INTERNAL_LOADGROUP) ; } void GxsGroupDialog::loadGroup(uint32_t token) From 3592d5bf5d35aee004742d06a949e4508a26bb32 Mon Sep 17 00:00:00 2001 From: Phenom Date: Fri, 21 Apr 2017 19:55:37 +0200 Subject: [PATCH 38/39] =?UTF-8?q?Fix=20GCC=20warnings:=20unused=20paramete?= =?UTF-8?q?r=20=E2=80=98names=E2=80=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /libretroshare/src/pqi/pqiservice.h:80: warning: unused parameter ‘names’ [-Wunused-parameter] virtual void getItemNames(std::map& names) const {} // This does nothing by default. Service should derive it in order to give info for the UI ^~~~~ --- libretroshare/src/pqi/pqiservice.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libretroshare/src/pqi/pqiservice.h b/libretroshare/src/pqi/pqiservice.h index b22a34aac..41c540d4c 100644 --- a/libretroshare/src/pqi/pqiservice.h +++ b/libretroshare/src/pqi/pqiservice.h @@ -77,7 +77,7 @@ public: virtual int tick() { return 0; } - virtual void getItemNames(std::map& names) const {} // This does nothing by default. Service should derive it in order to give info for the UI + virtual void getItemNames(std::map& /*names*/) const {} // This does nothing by default. Service should derive it in order to give info for the UI private: p3ServiceServerIface *mServiceServer; // const, no need for mutex. From 078913f0f34c6246e6f61290a308fb35b7a7886e Mon Sep 17 00:00:00 2001 From: Phenom Date: Fri, 21 Apr 2017 21:29:20 +0200 Subject: [PATCH 39/39] =?UTF-8?q?Fix=20GCC=20warnings:=20enumeration=20val?= =?UTF-8?q?ue=20=E2=80=98TYPE=5FIDENTITY=E2=80=99=20not=20handled=20in=20s?= =?UTF-8?q?witch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit warning: enumeration value ‘TYPE_IDENTITY’ not handled in switch [- Wswitch] switch (link.type()) { ^ --- retroshare-gui/src/util/HandleRichText.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/retroshare-gui/src/util/HandleRichText.cpp b/retroshare-gui/src/util/HandleRichText.cpp index c5f578d3a..96fd36d73 100644 --- a/retroshare-gui/src/util/HandleRichText.cpp +++ b/retroshare-gui/src/util/HandleRichText.cpp @@ -260,12 +260,13 @@ void RsHtml::anchorStylesheetForImg(QDomDocument &/*doc*/, QDomElement &/*elemen case RetroShareLink::TYPE_PERSON: case RetroShareLink::TYPE_FORUM: case RetroShareLink::TYPE_CHANNEL: - case RetroShareLink::TYPE_POSTED: case RetroShareLink::TYPE_SEARCH: case RetroShareLink::TYPE_MESSAGE: case RetroShareLink::TYPE_EXTRAFILE: case RetroShareLink::TYPE_PRIVATE_CHAT: case RetroShareLink::TYPE_PUBLIC_MSG: + case RetroShareLink::TYPE_POSTED: + case RetroShareLink::TYPE_IDENTITY: // not yet implemented break;