From ef0850e65b997dd0e0968e9725d6773bb54a26b8 Mon Sep 17 00:00:00 2001
From: csoler
Date: Mon, 19 Dec 2016 20:44:15 +0100
Subject: [PATCH 01/23] added recording system for usage cases of GXS ids
---
libretroshare/src/gxs/rsgenexchange.cc | 12 ++---
libretroshare/src/gxs/rsgixs.h | 2 +-
libretroshare/src/gxs/rsgxsutil.cc | 2 +-
libretroshare/src/gxstunnel/p3gxstunnel.cc | 2 +-
libretroshare/src/services/p3idservice.cc | 53 ++++++++++++++--------
libretroshare/src/services/p3idservice.h | 13 +++++-
6 files changed, 54 insertions(+), 30 deletions(-)
diff --git a/libretroshare/src/gxs/rsgenexchange.cc b/libretroshare/src/gxs/rsgenexchange.cc
index 46d0fd98a..3d1f2e109 100644
--- a/libretroshare/src/gxs/rsgenexchange.cc
+++ b/libretroshare/src/gxs/rsgenexchange.cc
@@ -470,8 +470,8 @@ int RsGenExchange::createGroupSignatures(RsTlvKeySignatureSet& signSet, RsTlvBin
if(GxsSecurity::getSignature((char*)grpData.bin_data, grpData.bin_len, authorKey, sign))
{
id_ret = SIGN_SUCCESS;
- mGixs->timeStampKey(grpMeta.mAuthorId) ;
- signSet.keySignSet[INDEX_AUTHEN_IDENTITY] = sign;
+ mGixs->timeStampKey(grpMeta.mAuthorId,"Creation of group author signature for GrpId" + grpMeta.mGroupId.toStdString()) ;
+ signSet.keySignSet[INDEX_AUTHEN_IDENTITY] = sign;
}
else
id_ret = SIGN_FAIL;
@@ -638,7 +638,7 @@ int RsGenExchange::createMsgSignatures(RsTlvKeySignatureSet& signSet, RsTlvBinar
if(GxsSecurity::getSignature((char*)msgData.bin_data, msgData.bin_len, authorKey, sign))
{
id_ret = SIGN_SUCCESS;
- mGixs->timeStampKey(msgMeta.mAuthorId) ;
+ mGixs->timeStampKey(msgMeta.mAuthorId,"Creating author signature in group " + msgMeta.mGroupId.toStdString() + ", msg " + msgMeta.mMsgId.toStdString()) ;
signSet.keySignSet[INDEX_AUTHEN_IDENTITY] = sign;
}
else
@@ -855,7 +855,7 @@ int RsGenExchange::validateMsg(RsNxsMsg *msg, const uint32_t& grpFlag, const uin
{
RsTlvKeySignature sign = metaData.signSet.keySignSet[INDEX_AUTHEN_IDENTITY];
idValidate &= GxsSecurity::validateNxsMsg(*msg, sign, authorKey);
- mGixs->timeStampKey(metaData.mAuthorId) ;
+ mGixs->timeStampKey(metaData.mAuthorId,"Validation of author signature. Grp="+metaData.mGroupId.toStdString()+", msg="+metaData.mMsgId.toStdString()) ;
}
else
{
@@ -986,7 +986,7 @@ int RsGenExchange::validateGrp(RsNxsGrp* grp)
#ifdef GEN_EXCH_DEBUG
std::cerr << " key ID validation result: " << idValidate << std::endl;
#endif
- mGixs->timeStampKey(metaData.mAuthorId) ;
+ mGixs->timeStampKey(metaData.mAuthorId,"Group author signature validation. GrpId=" + metaData.mGroupId.toStdString()) ;
}
else
{
@@ -3145,7 +3145,7 @@ bool RsGenExchange::updateValid(RsGxsGrpMetaData& oldGrpMeta, RsNxsGrp& newGrp)
// also check this is the latest published group
bool latest = newGrp.metaData->mPublishTs > oldGrpMeta.mPublishTs;
- mGixs->timeStampKey(newGrp.metaData->mAuthorId) ;
+ mGixs->timeStampKey(newGrp.metaData->mAuthorId,"Validation of signature for updated grp " + oldGrpMeta.mGroupId.toStdString()) ;
return GxsSecurity::validateNxsGrp(newGrp, adminSign, keyMit->second) && latest;
}
diff --git a/libretroshare/src/gxs/rsgixs.h b/libretroshare/src/gxs/rsgixs.h
index 5b12aa873..21c46d04d 100644
--- a/libretroshare/src/gxs/rsgixs.h
+++ b/libretroshare/src/gxs/rsgixs.h
@@ -125,7 +125,7 @@ public:
virtual bool getOwnIds(std::list& ids) = 0;
virtual bool isOwnId(const RsGxsId& key_id) = 0 ;
- virtual void timeStampKey(const RsGxsId& key_id) = 0 ;
+ virtual void timeStampKey(const RsGxsId& key_id,const std::string& reason) = 0 ;
// Key related interface - used for validating msgs and groups.
/*!
diff --git a/libretroshare/src/gxs/rsgxsutil.cc b/libretroshare/src/gxs/rsgxsutil.cc
index 29c9ae337..0b679fd41 100644
--- a/libretroshare/src/gxs/rsgxsutil.cc
+++ b/libretroshare/src/gxs/rsgxsutil.cc
@@ -339,7 +339,7 @@ bool RsGxsIntegrityCheck::check()
// Note: we could time_stamp even in the case where the id is not cached. Anyway, it's not really a problem here, since IDs have a high chance of
// behing eventually stamped.
- mGixs->timeStampKey(gxs_ids[n]) ;
+ mGixs->timeStampKey(gxs_ids[n],"Used in service (Integrity check)") ;
}
gxs_ids[n] = gxs_ids[gxs_ids.size()-1] ;
diff --git a/libretroshare/src/gxstunnel/p3gxstunnel.cc b/libretroshare/src/gxstunnel/p3gxstunnel.cc
index 0838bef50..c64cf6572 100644
--- a/libretroshare/src/gxstunnel/p3gxstunnel.cc
+++ b/libretroshare/src/gxstunnel/p3gxstunnel.cc
@@ -937,7 +937,7 @@ void p3GxsTunnelService::handleRecvDHPublicKey(RsGxsTunnelDHPublicKeyItem *item)
std::cerr << "(SS) Signature was verified and it doesn't check! This is a security issue!" << std::endl;
return ;
}
- mGixs->timeStampKey(item->signature.keyId) ;
+ mGixs->timeStampKey(item->signature.keyId,"Used to validate GXS tunnel DH half-key.") ;
#ifdef DEBUG_GXS_TUNNEL
std::cerr << " Signature checks! Sender's ID = " << senders_id << std::endl;
diff --git a/libretroshare/src/services/p3idservice.cc b/libretroshare/src/services/p3idservice.cc
index 6914ebaa5..c4ae86f52 100644
--- a/libretroshare/src/services/p3idservice.cc
+++ b/libretroshare/src/services/p3idservice.cc
@@ -128,8 +128,9 @@ RsIdentity *rsIdentity = NULL;
/* delays */
-#define CACHETEST_PERIOD 60
+#define CACHETEST_PERIOD 60
#define DELAY_BETWEEN_CONFIG_UPDATES 300
+#define GXS_MAX_KEY_TS_USAGE_MAP_SIZE 5
#define OWNID_RELOAD_DELAY 10
@@ -255,23 +256,33 @@ void p3IdService::slowIndicateConfigChanged()
}
time_t p3IdService::locked_getLastUsageTS(const RsGxsId& gxs_id)
{
- std::map::const_iterator it = mKeysTS.find(gxs_id) ;
+ std::map::const_iterator it = mKeysTS.find(gxs_id) ;
if(it == mKeysTS.end())
return 0 ;
else
- return it->second ;
+ return it->second.TS ;
}
-void p3IdService::timeStampKey(const RsGxsId& gxs_id)
+void p3IdService::timeStampKey(const RsGxsId& gxs_id, const std::string& reason)
{
if(rsReputations->isIdentityBanned(gxs_id) )
{
std::cerr << "(II) p3IdService:timeStampKey(): refusing to time stamp key " << gxs_id << " because it is banned." << std::endl;
return ;
}
+ std::cerr << "(II) time stamping key " << gxs_id << " for the following reason: " << reason << std::endl;
RS_STACK_MUTEX(mIdMtx) ;
- mKeysTS[gxs_id] = time(NULL) ;
+
+ time_t now = time(NULL) ;
+
+ keyTSInfo& info(mKeysTS[gxs_id]) ;
+
+ info.TS = now ;
+ info.usage_map[now] = reason ;
+
+ while(info.usage_map.size() > GXS_MAX_KEY_TS_USAGE_MAP_SIZE)
+ info.usage_map.erase(info.usage_map.begin());
slowIndicateConfigChanged() ;
}
@@ -286,7 +297,7 @@ bool p3IdService::loadList(std::list& items)
if( (lii = dynamic_cast(*it)) != NULL)
{
for(std::map::const_iterator it2 = lii->mTimeStamps.begin();it2!=lii->mTimeStamps.end();++it2)
- mKeysTS.insert(*it2) ;
+ mKeysTS[it2->first].TS = it2->second;
mContacts = lii->mContacts ;
}
@@ -307,7 +318,10 @@ bool p3IdService::saveList(bool& cleanup,std::list& items)
RS_STACK_MUTEX(mIdMtx) ;
cleanup = true ;
RsGxsIdLocalInfoItem *item = new RsGxsIdLocalInfoItem ;
- item->mTimeStamps = mKeysTS ;
+
+ for(std::map::const_iterator it(mKeysTS.begin());it!=mKeysTS.end();++it)
+ item->mTimeStamps[it->first] = it->second.TS;
+
item->mContacts = mContacts ;
items.push_back(item) ;
@@ -317,7 +331,7 @@ bool p3IdService::saveList(bool& cleanup,std::list& items)
class IdCacheEntryCleaner
{
public:
- IdCacheEntryCleaner(const std::map& last_usage_TSs) : mLastUsageTS(last_usage_TSs) {}
+ IdCacheEntryCleaner(const std::map& last_usage_TSs) : mLastUsageTS(last_usage_TSs) {}
bool processEntry(RsGxsIdCache& entry)
{
@@ -338,11 +352,11 @@ public:
return true ;
}
- std::map::const_iterator it = mLastUsageTS.find(gxs_id) ;
+ std::map::const_iterator it = mLastUsageTS.find(gxs_id) ;
bool no_ts = (it == mLastUsageTS.end()) ;
- time_t last_usage_ts = no_ts?0:(it->second);
+ time_t last_usage_ts = no_ts?0:(it->second.TS);
time_t max_keep_time ;
if(no_ts)
@@ -370,7 +384,7 @@ public:
}
std::list ids_to_delete ;
- const std::map& mLastUsageTS;
+ const std::map& mLastUsageTS;
};
void p3IdService::cleanUnusedKeys()
@@ -495,7 +509,7 @@ void p3IdService::notifyChanges(std::vector &changes)
// also time_stamp the key that this group represents
- timeStampKey(RsGxsId(*git)) ;
+ timeStampKey(RsGxsId(*git),"Group info changed") ;
++git;
}
@@ -892,7 +906,7 @@ bool p3IdService::signData(const uint8_t *data,uint32_t data_size,const RsGxsId&
return false ;
}
error_status = RS_GIXS_ERROR_NO_ERROR ;
- timeStampKey(own_gxs_id) ;
+ timeStampKey(own_gxs_id,"own GXS id") ;
return true ;
}
bool p3IdService::validateData(const uint8_t *data,uint32_t data_size,const RsTlvKeySignature& signature,bool force_load,uint32_t& signing_error)
@@ -929,7 +943,7 @@ bool p3IdService::validateData(const uint8_t *data,uint32_t data_size,const RsTl
}
signing_error = RS_GIXS_ERROR_NO_ERROR ;
- timeStampKey(signature.keyId) ;
+ timeStampKey(signature.keyId,"Used in signature checking." ) ;
return true ;
}
bool p3IdService::encryptData(const uint8_t *decrypted_data,uint32_t decrypted_data_size,uint8_t *& encrypted_data,uint32_t& encrypted_data_size,const RsGxsId& encryption_key_id,bool force_load,uint32_t& error_status)
@@ -957,7 +971,7 @@ bool p3IdService::encryptData(const uint8_t *decrypted_data,uint32_t decrypted_d
return false ;
}
error_status = RS_GIXS_ERROR_NO_ERROR ;
- timeStampKey(encryption_key_id) ;
+ timeStampKey(encryption_key_id,"Used to encrypt data") ;
return true ;
}
@@ -989,7 +1003,7 @@ bool p3IdService::decryptData(const uint8_t *encrypted_data,uint32_t encrypted_d
return false ;
}
error_status = RS_GIXS_ERROR_NO_ERROR ;
- timeStampKey(key_id) ;
+ timeStampKey(key_id,"Used to decrypt data") ;
return true ;
}
@@ -2399,7 +2413,8 @@ bool p3IdService::cache_load_ownids(uint32_t token)
// This prevents automatic deletion to get rid of them.
// In other words, own ids are always used.
- mKeysTS[RsGxsId(item->meta.mGroupId)] = time(NULL) ;
+
+ mKeysTS[RsGxsId(item->meta.mGroupId)].TS = time(NULL) ;
}
delete item ;
}
@@ -2691,7 +2706,7 @@ RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup(RsGxsGrpIte
std::cerr << std::endl;
return SERVICE_CREATE_FAIL;
}
- mKeysTS[RsGxsId(item->meta.mGroupId)] = time(NULL) ;
+ mKeysTS[RsGxsId(item->meta.mGroupId)].TS = time(NULL) ;
/********************* TEMP HACK UNTIL GXS FILLS IN GROUP_ID *****************/
@@ -2851,7 +2866,7 @@ RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup(RsGxsGrpIte
if (std::find(mOwnIds.begin(), mOwnIds.end(), gxsId) == mOwnIds.end())
{
mOwnIds.push_back(gxsId);
- mKeysTS[gxsId] = time(NULL) ;
+ mKeysTS[gxsId].TS = time(NULL) ;
}
}
diff --git a/libretroshare/src/services/p3idservice.h b/libretroshare/src/services/p3idservice.h
index f31bbaf50..f06042172 100644
--- a/libretroshare/src/services/p3idservice.h
+++ b/libretroshare/src/services/p3idservice.h
@@ -467,7 +467,7 @@ private:
void cleanUnusedKeys() ;
void slowIndicateConfigChanged() ;
- virtual void timeStampKey(const RsGxsId& id) ;
+ virtual void timeStampKey(const RsGxsId& id,const std::string& reason) ;
time_t locked_getLastUsageTS(const RsGxsId& gxs_id);
std::string genRandomId(int len = 20);
@@ -507,10 +507,19 @@ private:
private:
+ struct keyTSInfo
+ {
+ keyTSInfo() : TS(0) {}
+
+ time_t TS ;
+ std::map usage_map ;
+ };
+ friend class IdCacheEntryCleaner;
+
std::map > mIdsPendingCache;
std::map > mGroupNotPresent;
std::map > mIdsNotPresent;
- std::map mKeysTS ;
+ std::map mKeysTS ;
// keep a list of regular contacts. This is useful to sort IDs, and allow some services to priviledged ids only.
std::set mContacts;
From d3051eff1a121e965b479771487d209b17c9d50b Mon Sep 17 00:00:00 2001
From: csoler
Date: Wed, 21 Dec 2016 00:34:07 +0100
Subject: [PATCH 02/23] added display of usage statistics for GXS identities
---
libretroshare/src/gxs/rsgenexchange.h | 2 ++
libretroshare/src/gxs/rsgxsutil.cc | 20 +++++--------
libretroshare/src/pqi/p3servicecontrol.cc | 14 +++++++++
libretroshare/src/pqi/p3servicecontrol.h | 1 +
libretroshare/src/retroshare/rsidentity.h | 3 +-
.../src/retroshare/rsservicecontrol.h | 1 +
libretroshare/src/services/p3idservice.cc | 29 +++++++++++++++++--
retroshare-gui/src/gui/Identity/IdDialog.cpp | 18 ++++++++++++
retroshare-gui/src/gui/Identity/IdDialog.ui | 14 ++++++++-
9 files changed, 85 insertions(+), 17 deletions(-)
diff --git a/libretroshare/src/gxs/rsgenexchange.h b/libretroshare/src/gxs/rsgenexchange.h
index a391d47e0..2fc2ef6f7 100644
--- a/libretroshare/src/gxs/rsgenexchange.h
+++ b/libretroshare/src/gxs/rsgenexchange.h
@@ -656,6 +656,8 @@ public:
virtual void setSyncPeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs) ;
uint16_t serviceType() const { return mServType ; }
+ uint16_t serviceFullType() const { return ((uint32_t)mServType << 8) + (((uint32_t) RS_PKT_VERSION_SERVICE) << 24); }
+
protected:
/** Notifications **/
diff --git a/libretroshare/src/gxs/rsgxsutil.cc b/libretroshare/src/gxs/rsgxsutil.cc
index 0b679fd41..7fa83e3b0 100644
--- a/libretroshare/src/gxs/rsgxsutil.cc
+++ b/libretroshare/src/gxs/rsgxsutil.cc
@@ -139,7 +139,7 @@ bool RsGxsIntegrityCheck::check()
GxsMsgReq msgIds;
GxsMsgReq grps;
- std::set used_gxs_ids ;
+ std::map used_gxs_ids ;
std::set subscribed_groups ;
// compute hash and compare to stored value, if it fails then simply add it
@@ -172,7 +172,7 @@ bool RsGxsIntegrityCheck::check()
#endif
if(rsIdentity!=NULL && !rsIdentity->isBanned(grp->metaData->mAuthorId))
- used_gxs_ids.insert(grp->metaData->mAuthorId) ;
+ used_gxs_ids.insert(std::make_pair(grp->metaData->mAuthorId,grp->grpId)) ;
}
}
}
@@ -270,7 +270,7 @@ bool RsGxsIntegrityCheck::check()
GXSUTIL_DEBUG() << "TimeStamping message authors' key ID " << msg->metaData->mAuthorId << " in message " << msg->msgId << ", group ID " << msg->grpId<< std::endl;
#endif
if(rsIdentity!=NULL && !rsIdentity->isBanned(msg->metaData->mAuthorId))
- used_gxs_ids.insert(msg->metaData->mAuthorId) ;
+ used_gxs_ids.insert(std::make_pair(msg->metaData->mAuthorId,msg->metaData->mGroupId)) ;
}
delete msg;
@@ -297,9 +297,9 @@ bool RsGxsIntegrityCheck::check()
std::list connected_friends ;
rsPeers->getOnlineList(connected_friends) ;
- std::vector gxs_ids ;
+ std::vector > gxs_ids ;
- for(std::set::const_iterator it(used_gxs_ids.begin());it!=used_gxs_ids.end();++it)
+ for(std::map::const_iterator it(used_gxs_ids.begin());it!=used_gxs_ids.end();++it)
{
gxs_ids.push_back(*it) ;
#ifdef DEBUG_GXSUTIL
@@ -321,9 +321,9 @@ bool RsGxsIntegrityCheck::check()
GXSUTIL_DEBUG() << " requesting ID " << gxs_ids[n] ;
#endif
- if(!mGixs->haveKey(gxs_ids[n])) // checks if we have it already in the cache (conservative way to ensure that we atually have it)
+ if(!mGixs->haveKey(gxs_ids[n].first)) // checks if we have it already in the cache (conservative way to ensure that we atually have it)
{
- mGixs->requestKey(gxs_ids[n],connected_friends);
+ mGixs->requestKey(gxs_ids[n].first,connected_friends);
++nb_requested_not_in_cache ;
#ifdef DEBUG_GXSUTIL
@@ -335,12 +335,8 @@ bool RsGxsIntegrityCheck::check()
#ifdef DEBUG_GXSUTIL
GXSUTIL_DEBUG() << " ... already in cache" << std::endl;
#endif
-
- // Note: we could time_stamp even in the case where the id is not cached. Anyway, it's not really a problem here, since IDs have a high chance of
- // behing eventually stamped.
-
- mGixs->timeStampKey(gxs_ids[n],"Used in service (Integrity check)") ;
}
+ mGixs->timeStampKey(gxs_ids[n].first,"Author in group " + gxs_ids[n].second.toStdString() + " of service \"" + rsServiceControl->getServiceName(mGenExchangeClient->serviceFullType())) ;
gxs_ids[n] = gxs_ids[gxs_ids.size()-1] ;
gxs_ids.pop_back() ;
diff --git a/libretroshare/src/pqi/p3servicecontrol.cc b/libretroshare/src/pqi/p3servicecontrol.cc
index 11dd01520..a397a4e1c 100644
--- a/libretroshare/src/pqi/p3servicecontrol.cc
+++ b/libretroshare/src/pqi/p3servicecontrol.cc
@@ -362,6 +362,20 @@ void p3ServiceControl::getServiceChanges(std::set &updateSet)
mUpdatedSet.clear();
}
+std::string p3ServiceControl::getServiceName(uint32_t service_id)
+{
+ RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/
+
+ std::map::const_iterator it = mOwnServices.find(service_id) ;
+
+ if(it == mOwnServices.end())
+ {
+ std::cerr << "(EE) Cannot find own service for ID = " << std::hex << service_id << std::dec << std::endl;
+ return std::string();
+ }
+
+ return it->second.mServiceName;
+}
bool p3ServiceControl::getOwnServices(RsPeerServiceInfo &info)
{
diff --git a/libretroshare/src/pqi/p3servicecontrol.h b/libretroshare/src/pqi/p3servicecontrol.h
index e2a27ddc3..948481a2b 100644
--- a/libretroshare/src/pqi/p3servicecontrol.h
+++ b/libretroshare/src/pqi/p3servicecontrol.h
@@ -85,6 +85,7 @@ virtual const RsPeerId& getOwnId();
*/
virtual bool getOwnServices(RsPeerServiceInfo &info);
+virtual std::string getServiceName(uint32_t service_id) ;
// This is what is passed to peers, can be displayed by GUI too.
virtual bool getServicesAllowed(const RsPeerId &peerId, RsPeerServiceInfo &info);
diff --git a/libretroshare/src/retroshare/rsidentity.h b/libretroshare/src/retroshare/rsidentity.h
index e7a7abbe8..4a48b747c 100644
--- a/libretroshare/src/retroshare/rsidentity.h
+++ b/libretroshare/src/retroshare/rsidentity.h
@@ -184,7 +184,7 @@ public:
// Cyril: Reputation details. At some point we might want to merge information
// between the two into a single global score. Since the old reputation system
// is not finished yet, I leave this in place. We should decide what to do with it.
-
+#warning (cyril) possibly remove this old reputation field.
GxsReputation mReputation_oldSystem; // this is the old "mReputation" field, which apparently is not used.
RsReputations::ReputationInfo mReputation;
@@ -193,6 +193,7 @@ public:
// last usage
time_t mLastUsageTS ;
+ std::map mUseCases ;
};
diff --git a/libretroshare/src/retroshare/rsservicecontrol.h b/libretroshare/src/retroshare/rsservicecontrol.h
index 76c2ee811..a6d8fde7c 100644
--- a/libretroshare/src/retroshare/rsservicecontrol.h
+++ b/libretroshare/src/retroshare/rsservicecontrol.h
@@ -108,6 +108,7 @@ class RsServiceControl
virtual ~RsServiceControl() { return; }
virtual bool getOwnServices(RsPeerServiceInfo &info) = 0;
+virtual std::string getServiceName(uint32_t service_id) = 0;
virtual bool getServicesAllowed(const RsPeerId &peerId, RsPeerServiceInfo &info) = 0;
virtual bool getServicesProvided(const RsPeerId &peerId, RsPeerServiceInfo &info) = 0;
diff --git a/libretroshare/src/services/p3idservice.cc b/libretroshare/src/services/p3idservice.cc
index c4ae86f52..429562a18 100644
--- a/libretroshare/src/services/p3idservice.cc
+++ b/libretroshare/src/services/p3idservice.cc
@@ -279,10 +279,24 @@ void p3IdService::timeStampKey(const RsGxsId& gxs_id, const std::string& reason)
keyTSInfo& info(mKeysTS[gxs_id]) ;
info.TS = now ;
- info.usage_map[now] = reason ;
+ info.usage_map[reason] = now;
while(info.usage_map.size() > GXS_MAX_KEY_TS_USAGE_MAP_SIZE)
- info.usage_map.erase(info.usage_map.begin());
+ {
+ // This is very costly, but normally the outerloop should never be rolled more than once.
+
+ std::map::iterator best_it ;
+ time_t best_time = now+1;
+
+ for(std::map::iterator it(info.usage_map.begin());it!=info.usage_map.end();++it)
+ if(it->second < best_time)
+ {
+ best_time = it->second ;
+ best_it = it;
+ }
+
+ info.usage_map.erase(best_it) ;
+ }
slowIndicateConfigChanged() ;
}
@@ -566,7 +580,16 @@ bool p3IdService::getIdDetails(const RsGxsId &id, RsIdentityDetails &details)
rsReputations->setOwnOpinion(id,RsReputations::OPINION_POSITIVE) ;
details = data.details;
- details.mLastUsageTS = locked_getLastUsageTS(id) ;
+
+ std::map::const_iterator it = mKeysTS.find(id) ;
+
+ if(it == mKeysTS.end())
+ details.mLastUsageTS = 0 ;
+ else
+ {
+ details.mLastUsageTS = it->second.TS ;
+ details.mUseCases = it->second.usage_map ;
+ }
// one utf8 symbol can be at most 4 bytes long - would be better to measure real unicode length !!!
if(details.mNickname.length() > RSID_MAXIMUM_NICKNAME_SIZE*4)
diff --git a/retroshare-gui/src/gui/Identity/IdDialog.cpp b/retroshare-gui/src/gui/Identity/IdDialog.cpp
index 20bef5ccf..0ca6be250 100644
--- a/retroshare-gui/src/gui/Identity/IdDialog.cpp
+++ b/retroshare-gui/src/gui/Identity/IdDialog.cpp
@@ -1849,6 +1849,24 @@ void IdDialog::insertIdDetails(uint32_t token)
default:
std::cerr << "Unexpected value in own opinion: " << info.mOwnOpinion << std::endl;
}
+
+ // now fill in usage cases
+
+ RsIdentityDetails det ;
+ rsIdentity->getIdDetails(RsGxsId(data.mMeta.mGroupId),det) ;
+
+ QString usage_txt ;
+ std::map rmap ;
+ for(std::map::const_iterator it(det.mUseCases.begin());it!=det.mUseCases.end();++it)
+ rmap.insert(std::make_pair(it->second,it->first)) ;
+
+ for(std::map::const_iterator it(rmap.begin());it!=rmap.end();++it)
+ usage_txt += QString("")+ getHumanReadableDuration(now - data.mLastUsageTS) + " \t: " + QString::fromStdString(it->second) + "
" ;
+
+ if(usage_txt.isNull())
+ usage_txt = tr("[Unused]") ;
+
+ ui->usageStatistics_TB->setText(usage_txt) ;
}
void IdDialog::modifyReputation()
diff --git a/retroshare-gui/src/gui/Identity/IdDialog.ui b/retroshare-gui/src/gui/Identity/IdDialog.ui
index bb075b56f..3dceaa373 100644
--- a/retroshare-gui/src/gui/Identity/IdDialog.ui
+++ b/retroshare-gui/src/gui/Identity/IdDialog.ui
@@ -7,7 +7,7 @@
0
0
1269
- 911
+ 1040
@@ -595,6 +595,18 @@ p, li { white-space: pre-wrap; }
+ -
+
+
+ Usage statistics
+
+
+
-
+
+
+
+
+
-
From 0a3ec9706d73bf6bd8f9caa2d2a199c131388398 Mon Sep 17 00:00:00 2001
From: csoler
Date: Thu, 22 Dec 2016 00:14:16 +0100
Subject: [PATCH 03/23] added statistics info for key requests
---
libretroshare/src/chat/distributedchat.cc | 4 ++--
libretroshare/src/grouter/p3grouter.cc | 12 ++++++------
libretroshare/src/grouter/p3grouter.h | 2 +-
libretroshare/src/gxs/rsgenexchange.cc | 6 +++---
libretroshare/src/gxs/rsgenexchange.h | 2 +-
libretroshare/src/gxs/rsgixs.h | 4 ++--
libretroshare/src/gxs/rsgxsutil.cc | 4 ++--
libretroshare/src/services/p3gxscircles.cc | 2 +-
libretroshare/src/services/p3idservice.cc | 18 +++++++++++-------
libretroshare/src/services/p3idservice.h | 4 ++--
libretroshare/src/util/rsprint.cc | 6 +++++-
libretroshare/src/util/rsprint.h | 2 +-
12 files changed, 37 insertions(+), 29 deletions(-)
diff --git a/libretroshare/src/chat/distributedchat.cc b/libretroshare/src/chat/distributedchat.cc
index 9f4a4274e..dc4da67c0 100644
--- a/libretroshare/src/chat/distributedchat.cc
+++ b/libretroshare/src/chat/distributedchat.cc
@@ -220,7 +220,7 @@ bool DistributedChatService::checkSignature(RsChatLobbyBouncingObject *obj,const
// network pre-request key to allow message authentication.
- mGixs->requestKey(obj->signature.keyId,peer_list);
+ mGixs->requestKey(obj->signature.keyId,peer_list,"Needed for chat lobby "+RsUtil::NumberToString(obj->lobby_id,true));
uint32_t size = obj->signed_serial_size() ;
RsTemporaryMemory memory(size) ;
@@ -238,7 +238,7 @@ bool DistributedChatService::checkSignature(RsChatLobbyBouncingObject *obj,const
uint32_t error_status ;
- if(!mGixs->validateData(memory,obj->signed_serial_size(),obj->signature,false,error_status))
+ if(!mGixs->validateData(memory,obj->signed_serial_size(),obj->signature,false,"Chat lobby "+RsUtil::NumberToString(obj->lobby_id,true),error_status))
{
bool res = false ;
diff --git a/libretroshare/src/grouter/p3grouter.cc b/libretroshare/src/grouter/p3grouter.cc
index 5c51a196d..c9bc1fb13 100644
--- a/libretroshare/src/grouter/p3grouter.cc
+++ b/libretroshare/src/grouter/p3grouter.cc
@@ -1555,7 +1555,7 @@ void p3GRouter::handleIncomingReceiptItem(RsGRouterSignedReceiptItem *receipt_it
uint32_t error_status ;
- if(! verifySignedDataItem(receipt_item,error_status))
+ if(! verifySignedDataItem(receipt_item,"GRouter incoming receipt item",error_status))
if( (it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_IS_ORIGIN) || (error_status != RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE))
{
std::cerr << " checking receipt signature : FAILED. Receipt is dropped. Error status=" << error_status << std::endl;
@@ -1711,7 +1711,7 @@ void p3GRouter::handleIncomingDataItem(RsGRouterGenericDataItem *data_item)
#endif
uint32_t error_status ;
- if(!verifySignedDataItem(data_item,error_status)) // we should get proper flags out of this
+ if(!verifySignedDataItem(data_item,"Incoming distant message",error_status)) // we should get proper flags out of this
{
std::cerr << " verifying item signature: FAILED! Droping that item" ;
std::cerr << " You probably received a message from a person you don't have key." << std::endl;
@@ -1980,7 +1980,7 @@ bool p3GRouter::signDataItem(RsGRouterAbstractMsgItem *item,const RsGxsId& signi
return false ;
}
}
-bool p3GRouter::verifySignedDataItem(RsGRouterAbstractMsgItem *item,uint32_t& error_status)
+bool p3GRouter::verifySignedDataItem(RsGRouterAbstractMsgItem *item,const std::string& info,uint32_t& error_status)
{
try
{
@@ -1999,7 +1999,7 @@ bool p3GRouter::verifySignedDataItem(RsGRouterAbstractMsgItem *item,uint32_t& er
if(!item->serialise_signed_data(data,data_size))
throw std::runtime_error("Cannot serialise signed data.") ;
- if(!mGixs->validateData(data,data_size,item->signature,true,error_status))
+ if(!mGixs->validateData(data,data_size,item->signature,true,info, error_status))
{
switch(error_status)
{
@@ -2010,7 +2010,7 @@ bool p3GRouter::verifySignedDataItem(RsGRouterAbstractMsgItem *item,uint32_t& er
std::cerr << "(EE) Key for GXS Id " << item->signature.keyId << " is not available. Cannot verify. Asking key to peer " << item->PeerId() << std::endl;
- mGixs->requestKey(item->signature.keyId,peer_ids) ; // request the key around
+ mGixs->requestKey(item->signature.keyId,peer_ids,info) ; // request the key around
}
break ;
case RsGixs::RS_GIXS_ERROR_SIGNATURE_MISMATCH: std::cerr << "(EE) Signature mismatch. Spoofing/Corrupted/MITM?." << std::endl;
@@ -2116,7 +2116,7 @@ bool p3GRouter::sendData(const RsGxsId& destination,const GRouterServiceId& clie
// Verify the signature. If that fails, there's a bug somewhere!!
uint32_t error_status;
- if(!verifySignedDataItem(data_item,error_status))
+ if(!verifySignedDataItem(data_item,"GRouter own signature check for outgoing msg",error_status))
{
std::cerr << "Cannot verify data item that was just signed. Some error occured!" << std::endl;
delete data_item;
diff --git a/libretroshare/src/grouter/p3grouter.h b/libretroshare/src/grouter/p3grouter.h
index 9ddf50149..19d704add 100644
--- a/libretroshare/src/grouter/p3grouter.h
+++ b/libretroshare/src/grouter/p3grouter.h
@@ -254,7 +254,7 @@ private:
// signs an item with the given key.
bool signDataItem(RsGRouterAbstractMsgItem *item,const RsGxsId& id) ;
- bool verifySignedDataItem(RsGRouterAbstractMsgItem *item, uint32_t &error_status) ;
+ bool verifySignedDataItem(RsGRouterAbstractMsgItem *item, const std::string &info, uint32_t &error_status) ;
bool encryptDataItem(RsGRouterGenericDataItem *item,const RsGxsId& destination_key) ;
bool decryptDataItem(RsGRouterGenericDataItem *item) ;
diff --git a/libretroshare/src/gxs/rsgenexchange.cc b/libretroshare/src/gxs/rsgenexchange.cc
index 3d1f2e109..2075bc7c1 100644
--- a/libretroshare/src/gxs/rsgenexchange.cc
+++ b/libretroshare/src/gxs/rsgenexchange.cc
@@ -855,7 +855,7 @@ int RsGenExchange::validateMsg(RsNxsMsg *msg, const uint32_t& grpFlag, const uin
{
RsTlvKeySignature sign = metaData.signSet.keySignSet[INDEX_AUTHEN_IDENTITY];
idValidate &= GxsSecurity::validateNxsMsg(*msg, sign, authorKey);
- mGixs->timeStampKey(metaData.mAuthorId,"Validation of author signature. Grp="+metaData.mGroupId.toStdString()+", msg="+metaData.mMsgId.toStdString()) ;
+ mGixs->timeStampKey(metaData.mAuthorId,"Validation of author signature, service: " + rsServiceControl->getServiceName(serviceFullType()) + ". Grp="+metaData.mGroupId.toStdString()+", msg="+metaData.mMsgId.toStdString()) ;
}
else
{
@@ -909,7 +909,7 @@ int RsGenExchange::validateMsg(RsNxsMsg *msg, const uint32_t& grpFlag, const uin
{
std::list peers;
peers.push_back(msg->PeerId());
- mGixs->requestKey(metaData.mAuthorId, peers);
+ mGixs->requestKey(metaData.mAuthorId, peers,"Validation of author signature, service: " + rsServiceControl->getServiceName(serviceFullType()) + ". Grp="+metaData.mGroupId.toStdString()+", msg="+metaData.mMsgId.toStdString());
#ifdef GEN_EXCH_DEBUG
std::cerr << ", Key missing. Retry later." << std::endl;
@@ -1004,7 +1004,7 @@ int RsGenExchange::validateGrp(RsNxsGrp* grp)
#endif
std::list peers;
peers.push_back(grp->PeerId());
- mGixs->requestKey(metaData.mAuthorId, peers);
+ mGixs->requestKey(metaData.mAuthorId, peers,"Group author signature validation. GrpId=" + metaData.mGroupId.toStdString());
return VALIDATE_FAIL_TRY_LATER;
}
}
diff --git a/libretroshare/src/gxs/rsgenexchange.h b/libretroshare/src/gxs/rsgenexchange.h
index 2fc2ef6f7..0614ed2b1 100644
--- a/libretroshare/src/gxs/rsgenexchange.h
+++ b/libretroshare/src/gxs/rsgenexchange.h
@@ -656,7 +656,7 @@ public:
virtual void setSyncPeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs) ;
uint16_t serviceType() const { return mServType ; }
- uint16_t serviceFullType() const { return ((uint32_t)mServType << 8) + (((uint32_t) RS_PKT_VERSION_SERVICE) << 24); }
+ uint32_t serviceFullType() const { return ((uint32_t)mServType << 8) + (((uint32_t) RS_PKT_VERSION_SERVICE) << 24); }
protected:
diff --git a/libretroshare/src/gxs/rsgixs.h b/libretroshare/src/gxs/rsgixs.h
index 21c46d04d..a210064c2 100644
--- a/libretroshare/src/gxs/rsgixs.h
+++ b/libretroshare/src/gxs/rsgixs.h
@@ -117,7 +117,7 @@ public:
*/
virtual bool signData(const uint8_t *data,uint32_t data_size,const RsGxsId& signer_id,RsTlvKeySignature& signature,uint32_t& signing_error) = 0 ;
- virtual bool validateData(const uint8_t *data,uint32_t data_size,const RsTlvKeySignature& signature,bool force_load,uint32_t& signing_error) = 0 ;
+ virtual bool validateData(const uint8_t *data,uint32_t data_size,const RsTlvKeySignature& signature,bool force_load,const std::string& info_string,uint32_t& signing_error) = 0 ;
virtual bool encryptData(const uint8_t *clear_data,uint32_t clear_data_size,uint8_t *& encrypted_data,uint32_t& encrypted_data_size,const RsGxsId& encryption_key_id,bool force_load,uint32_t& encryption_error) = 0 ;
virtual bool decryptData(const uint8_t *encrypted_data,uint32_t encrypted_data_size,uint8_t *& clear_data,uint32_t& clear_data_size,const RsGxsId& encryption_key_id,uint32_t& encryption_error) = 0 ;
@@ -149,7 +149,7 @@ public:
* @param keyref the KeyRef of the key being requested
* @return will
*/
- virtual bool requestKey(const RsGxsId &id, const std::list &peers) = 0;
+ virtual bool requestKey(const RsGxsId &id, const std::list &peers,const std::string& info) = 0;
virtual bool requestPrivateKey(const RsGxsId &id) = 0;
diff --git a/libretroshare/src/gxs/rsgxsutil.cc b/libretroshare/src/gxs/rsgxsutil.cc
index 7fa83e3b0..c4dc5304f 100644
--- a/libretroshare/src/gxs/rsgxsutil.cc
+++ b/libretroshare/src/gxs/rsgxsutil.cc
@@ -323,7 +323,7 @@ bool RsGxsIntegrityCheck::check()
if(!mGixs->haveKey(gxs_ids[n].first)) // checks if we have it already in the cache (conservative way to ensure that we atually have it)
{
- mGixs->requestKey(gxs_ids[n].first,connected_friends);
+ mGixs->requestKey(gxs_ids[n].first,connected_friends,"Author in group " + gxs_ids[n].second.toStdString() + " of service \"" + rsServiceControl->getServiceName(mGenExchangeClient->serviceFullType())+"\"") ;
++nb_requested_not_in_cache ;
#ifdef DEBUG_GXSUTIL
@@ -336,7 +336,7 @@ bool RsGxsIntegrityCheck::check()
GXSUTIL_DEBUG() << " ... already in cache" << std::endl;
#endif
}
- mGixs->timeStampKey(gxs_ids[n].first,"Author in group " + gxs_ids[n].second.toStdString() + " of service \"" + rsServiceControl->getServiceName(mGenExchangeClient->serviceFullType())) ;
+ mGixs->timeStampKey(gxs_ids[n].first,"Author in group " + gxs_ids[n].second.toStdString() + " of service \"" + rsServiceControl->getServiceName(mGenExchangeClient->serviceFullType())+"\"") ;
gxs_ids[n] = gxs_ids[gxs_ids.size()-1] ;
gxs_ids.pop_back() ;
diff --git a/libretroshare/src/services/p3gxscircles.cc b/libretroshare/src/services/p3gxscircles.cc
index b36dc141e..c9087cea1 100644
--- a/libretroshare/src/services/p3gxscircles.cc
+++ b/libretroshare/src/services/p3gxscircles.cc
@@ -1094,7 +1094,7 @@ bool p3GxsCircles::locked_processLoadingCacheEntry(RsGxsCircleCache& cache)
rsPeers->getOnlineList(peers) ;
}
- mIdentities->requestKey(pit->first, peers);
+ mIdentities->requestKey(pit->first, peers,"Membership status check in Circle "+cache.mCircleName+" ("+cache.mCircleId.toStdString()+")");
//isUnprocessedPeers = true;
}
}
diff --git a/libretroshare/src/services/p3idservice.cc b/libretroshare/src/services/p3idservice.cc
index 429562a18..72cd3231e 100644
--- a/libretroshare/src/services/p3idservice.cc
+++ b/libretroshare/src/services/p3idservice.cc
@@ -523,7 +523,7 @@ void p3IdService::notifyChanges(std::vector &changes)
// also time_stamp the key that this group represents
- timeStampKey(RsGxsId(*git),"Group info changed") ;
+ timeStampKey(RsGxsId(*git),"Group meta data changed") ;
++git;
}
@@ -789,7 +789,7 @@ static void mergeIds(std::map >& idmap,const RsGxsId
old_peers.push_back(*it) ;
}
-bool p3IdService::requestKey(const RsGxsId &id, const std::list& peers)
+bool p3IdService::requestKey(const RsGxsId &id, const std::list& peers,const std::string& info)
{
if(id.isNull())
{
@@ -815,7 +815,7 @@ bool p3IdService::requestKey(const RsGxsId &id, const std::list& peers
std::cerr << "(II) not requesting Key " << id << " because it has been banned." << std::endl;
{
- RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/
+ RS_STACK_MUTEX(mIdMtx); /********** STACK LOCKED MTX ******/
mIdsNotPresent.erase(id) ;
}
return true;
@@ -833,6 +833,10 @@ bool p3IdService::requestKey(const RsGxsId &id, const std::list& peers
return true ;
}
}
+ {
+ RS_STACK_MUTEX(mIdMtx); /********** STACK LOCKED MTX ******/
+ mKeysTS[id].usage_map["Requested to friends: "+info] = time(NULL) ;
+ }
return cache_request_load(id, peers);
}
@@ -929,10 +933,10 @@ bool p3IdService::signData(const uint8_t *data,uint32_t data_size,const RsGxsId&
return false ;
}
error_status = RS_GIXS_ERROR_NO_ERROR ;
- timeStampKey(own_gxs_id,"own GXS id") ;
+ timeStampKey(own_gxs_id,"Own GXS id") ;
return true ;
}
-bool p3IdService::validateData(const uint8_t *data,uint32_t data_size,const RsTlvKeySignature& signature,bool force_load,uint32_t& signing_error)
+bool p3IdService::validateData(const uint8_t *data,uint32_t data_size,const RsTlvKeySignature& signature,bool force_load,const std::string& info_string,uint32_t& signing_error)
{
// RsIdentityDetails details ;
// getIdDetails(signature.keyId,details);
@@ -966,7 +970,7 @@ bool p3IdService::validateData(const uint8_t *data,uint32_t data_size,const RsTl
}
signing_error = RS_GIXS_ERROR_NO_ERROR ;
- timeStampKey(signature.keyId,"Used in signature checking." ) ;
+ timeStampKey(signature.keyId,"Used in signature checking: "+info_string ) ;
return true ;
}
bool p3IdService::encryptData(const uint8_t *decrypted_data,uint32_t decrypted_data_size,uint8_t *& encrypted_data,uint32_t& encrypted_data_size,const RsGxsId& encryption_key_id,bool force_load,uint32_t& error_status)
@@ -2531,7 +2535,7 @@ bool p3IdService::cachetest_handlerequest(uint32_t token)
if (!haveKey(*vit))
{
std::list nullpeers;
- requestKey(*vit, nullpeers);
+ requestKey(*vit, nullpeers,"Cache test in p3IdService");
#ifdef DEBUG_IDS
std::cerr << "p3IdService::cachetest_request() Requested Key Id: " << *vit;
diff --git a/libretroshare/src/services/p3idservice.h b/libretroshare/src/services/p3idservice.h
index f06042172..5ca5d1c75 100644
--- a/libretroshare/src/services/p3idservice.h
+++ b/libretroshare/src/services/p3idservice.h
@@ -287,7 +287,7 @@ public:
virtual bool isOwnId(const RsGxsId& key_id) ;
virtual bool signData(const uint8_t *data,uint32_t data_size,const RsGxsId& signer_id,RsTlvKeySignature& signature,uint32_t& signing_error) ;
- virtual bool validateData(const uint8_t *data,uint32_t data_size,const RsTlvKeySignature& signature,bool force_load,uint32_t& signing_error) ;
+ virtual bool validateData(const uint8_t *data,uint32_t data_size,const RsTlvKeySignature& signature,bool force_load,const std::string& info_string,uint32_t& signing_error) ;
virtual bool encryptData(const uint8_t *decrypted_data,uint32_t decrypted_data_size,uint8_t *& encrypted_data,uint32_t& encrypted_data_size,const RsGxsId& encryption_key_id,bool force_load,uint32_t& encryption_error) ;
virtual bool decryptData(const uint8_t *encrypted_data,uint32_t encrypted_data_size,uint8_t *& decrypted_data,uint32_t& decrypted_data_size,const RsGxsId& encryption_key_id,uint32_t& encryption_error) ;
@@ -298,7 +298,7 @@ public:
virtual bool getKey(const RsGxsId &id, RsTlvPublicRSAKey &key);
virtual bool getPrivateKey(const RsGxsId &id, RsTlvPrivateRSAKey &key);
- virtual bool requestKey(const RsGxsId &id, const std::list &peers);
+ virtual bool requestKey(const RsGxsId &id, const std::list &peers, const std::string &info);
virtual bool requestPrivateKey(const RsGxsId &id);
diff --git a/libretroshare/src/util/rsprint.cc b/libretroshare/src/util/rsprint.cc
index 5735088f4..e692f6c26 100644
--- a/libretroshare/src/util/rsprint.cc
+++ b/libretroshare/src/util/rsprint.cc
@@ -36,9 +36,13 @@
#include
#endif
-std::string RsUtil::NumberToString(uint64_t n)
+std::string RsUtil::NumberToString(uint64_t n,bool hex)
{
std::ostringstream os ;
+
+ if(hex)
+ os << std::hex ;
+
os << n ;
os.flush() ;
diff --git a/libretroshare/src/util/rsprint.h b/libretroshare/src/util/rsprint.h
index ebcccb8ef..37207ebde 100644
--- a/libretroshare/src/util/rsprint.h
+++ b/libretroshare/src/util/rsprint.h
@@ -36,7 +36,7 @@ namespace RsUtil {
std::string BinToHex(const std::string &bin);
std::string BinToHex(const char *arr, const uint32_t len);
std::string BinToHex(const unsigned char *arr, const uint32_t len);
-std::string NumberToString(uint64_t n);
+std::string NumberToString(uint64_t n, bool hex=false);
std::string HashId(const std::string &id, bool reverse = false);
//std::string AccurateTimeString();
From 8b9038a028e4fe8c4432c03e9f15a6eeca12019f Mon Sep 17 00:00:00 2001
From: csoler
Date: Thu, 22 Dec 2016 11:21:49 +0100
Subject: [PATCH 04/23] improved display/wording of usage statstics in People
---
libretroshare/src/gxs/rsgxsutil.cc | 4 ++--
retroshare-gui/src/gui/Identity/IdDialog.cpp | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/libretroshare/src/gxs/rsgxsutil.cc b/libretroshare/src/gxs/rsgxsutil.cc
index c4dc5304f..8b2b25a5d 100644
--- a/libretroshare/src/gxs/rsgxsutil.cc
+++ b/libretroshare/src/gxs/rsgxsutil.cc
@@ -323,7 +323,7 @@ bool RsGxsIntegrityCheck::check()
if(!mGixs->haveKey(gxs_ids[n].first)) // checks if we have it already in the cache (conservative way to ensure that we atually have it)
{
- mGixs->requestKey(gxs_ids[n].first,connected_friends,"Author in group " + gxs_ids[n].second.toStdString() + " of service \"" + rsServiceControl->getServiceName(mGenExchangeClient->serviceFullType())+"\"") ;
+ mGixs->requestKey(gxs_ids[n].first,connected_friends,"Author in service \"" + rsServiceControl->getServiceName(mGenExchangeClient->serviceFullType())+"\" (group ID " + gxs_ids[n].second.toStdString() + ")" ) ;
++nb_requested_not_in_cache ;
#ifdef DEBUG_GXSUTIL
@@ -336,7 +336,7 @@ bool RsGxsIntegrityCheck::check()
GXSUTIL_DEBUG() << " ... already in cache" << std::endl;
#endif
}
- mGixs->timeStampKey(gxs_ids[n].first,"Author in group " + gxs_ids[n].second.toStdString() + " of service \"" + rsServiceControl->getServiceName(mGenExchangeClient->serviceFullType())+"\"") ;
+ mGixs->timeStampKey(gxs_ids[n].first,"Author in service \"" + rsServiceControl->getServiceName(mGenExchangeClient->serviceFullType())+"\" (group ID " + gxs_ids[n].second.toStdString() + ")");
gxs_ids[n] = gxs_ids[gxs_ids.size()-1] ;
gxs_ids.pop_back() ;
diff --git a/retroshare-gui/src/gui/Identity/IdDialog.cpp b/retroshare-gui/src/gui/Identity/IdDialog.cpp
index 0ca6be250..5f7a20010 100644
--- a/retroshare-gui/src/gui/Identity/IdDialog.cpp
+++ b/retroshare-gui/src/gui/Identity/IdDialog.cpp
@@ -1864,7 +1864,7 @@ void IdDialog::insertIdDetails(uint32_t token)
usage_txt += QString("")+ getHumanReadableDuration(now - data.mLastUsageTS) + " \t: " + QString::fromStdString(it->second) + "
" ;
if(usage_txt.isNull())
- usage_txt = tr("[Unused]") ;
+ usage_txt = tr("[No record in current session]") ;
ui->usageStatistics_TB->setText(usage_txt) ;
}
From 72fb8f17a99cfd81e4333a32c0e4827dc5baae35 Mon Sep 17 00:00:00 2001
From: csoler
Date: Fri, 23 Dec 2016 17:52:02 +0100
Subject: [PATCH 05/23] changed the reputation system to output a level that
differentiate your own opinion to your friends opinion
---
libretroshare/src/chat/distributedchat.cc | 4 +-
libretroshare/src/grouter/p3grouter.cc | 2 +-
libretroshare/src/gxs/rsgenexchange.cc | 19 ++---
libretroshare/src/gxs/rsgxsnetservice.cc | 51 +++++++------
libretroshare/src/gxs/rsgxsutil.cc | 4 +-
libretroshare/src/retroshare/rsidentity.h | 11 ++-
libretroshare/src/retroshare/rsreputations.h | 22 ++++--
libretroshare/src/services/p3gxsreputation.cc | 75 +++++++++++++++----
libretroshare/src/services/p3gxsreputation.h | 17 +++--
libretroshare/src/services/p3idservice.cc | 9 +--
libretroshare/src/services/p3idservice.h | 2 +-
.../src/gui/Identity/IdDetailsDialog.cpp | 7 +-
retroshare-gui/src/gui/Identity/IdDialog.cpp | 25 +++++--
retroshare-gui/src/gui/gxs/GxsIdDetails.cpp | 6 +-
.../src/gui/gxs/GxsIdTreeWidgetItem.cpp | 6 +-
.../gui/gxsforums/GxsForumThreadWidget.cpp | 7 +-
16 files changed, 173 insertions(+), 94 deletions(-)
diff --git a/libretroshare/src/chat/distributedchat.cc b/libretroshare/src/chat/distributedchat.cc
index dc4da67c0..8fbc8f624 100644
--- a/libretroshare/src/chat/distributedchat.cc
+++ b/libretroshare/src/chat/distributedchat.cc
@@ -138,7 +138,7 @@ bool DistributedChatService::handleRecvChatLobbyMsgItem(RsChatMsgItem *ci)
return false ;
}
- if(rsIdentity->isBanned(cli->signature.keyId))
+ if(rsIdentity->overallReputationLevel(cli->signature.keyId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
{
std::cerr << "(WW) Received lobby msg/item from banned identity " << cli->signature.keyId << ". Dropping it." << std::endl;
return false ;
@@ -647,7 +647,7 @@ void DistributedChatService::handleRecvChatLobbyEventItem(RsChatLobbyEventItem *
#endif
time_t now = time(NULL) ;
- if(rsIdentity->isBanned(item->signature.keyId))
+ if(rsIdentity->overallReputationLevel(item->signature.keyId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
{
std::cerr << "(WW) Received lobby msg/item from banned identity " << item->signature.keyId << ". Dropping it." << std::endl;
return ;
diff --git a/libretroshare/src/grouter/p3grouter.cc b/libretroshare/src/grouter/p3grouter.cc
index c9bc1fb13..1cb8cb360 100644
--- a/libretroshare/src/grouter/p3grouter.cc
+++ b/libretroshare/src/grouter/p3grouter.cc
@@ -1984,7 +1984,7 @@ bool p3GRouter::verifySignedDataItem(RsGRouterAbstractMsgItem *item,const std::s
{
try
{
- if(rsIdentity->isBanned(item->signature.keyId))
+ if(rsIdentity->overallReputationLevel(item->signature.keyId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
{
std::cerr << "(WW) received global router message from banned identity " << item->signature.keyId << ". Rejecting the message." << std::endl;
return false ;
diff --git a/libretroshare/src/gxs/rsgenexchange.cc b/libretroshare/src/gxs/rsgenexchange.cc
index 2075bc7c1..25d4e52d8 100644
--- a/libretroshare/src/gxs/rsgenexchange.cc
+++ b/libretroshare/src/gxs/rsgenexchange.cc
@@ -880,20 +880,13 @@ int RsGenExchange::validateMsg(RsNxsMsg *msg, const uint32_t& grpFlag, const uin
else
{
- // now check reputation of the message author
- float reputation_threshold = RsReputations::REPUTATION_THRESHOLD_DEFAULT;
-
- if( (signFlag & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG_KNOWN) && !(details.mFlags & RS_IDENTITY_FLAGS_PGP_KNOWN))
- reputation_threshold = RsReputations::REPUTATION_THRESHOLD_ANTI_SPAM;
- else if( (signFlag & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) && !(details.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED))
- reputation_threshold = RsReputations::REPUTATION_THRESHOLD_ANTI_SPAM;
- else
- reputation_threshold = RsReputations::REPUTATION_THRESHOLD_DEFAULT;
-
- if(details.mReputation.mOverallReputationScore < reputation_threshold)
+ // now check reputation of the message author. The reputation will need to be at least as high as this value for the msg to validate.
+ // At validation step, we accept all messages, except the ones signed by locally rejected identities.
+
+ if(details.mReputation.mOverallReputationLevel == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
{
#ifdef GEN_EXCH_DEBUG
- std::cerr << "RsGenExchange::validateMsg(): message from " << metaData.mAuthorId << ", rejected because reputation score (" << details.mReputation.mOverallReputationScore <<") is below the accepted threshold (" << reputation_threshold << ")" << std::endl;
+ std::cerr << "RsGenExchange::validateMsg(): message from " << metaData.mAuthorId << ", rejected because reputation score (" << details.mReputation.mOverallReputationLevel <<") is below the accepted threshold (" << reputation_threshold << ")" << std::endl;
#endif
idValidate = false ;
}
@@ -903,7 +896,7 @@ int RsGenExchange::validateMsg(RsNxsMsg *msg, const uint32_t& grpFlag, const uin
#endif
}
- }
+ }
}
else
{
diff --git a/libretroshare/src/gxs/rsgxsnetservice.cc b/libretroshare/src/gxs/rsgxsnetservice.cc
index e19052257..dd7ffebf7 100644
--- a/libretroshare/src/gxs/rsgxsnetservice.cc
+++ b/libretroshare/src/gxs/rsgxsnetservice.cc
@@ -2810,16 +2810,13 @@ void RsGxsNetService::locked_genReqMsgTransaction(NxsTransaction* tr)
if(reqListSize < MAX_REQLIST_SIZE && msgIdSet.find(msgId) == msgIdSet.end())
{
- // if reputation is in reputations cache then proceed
- // or if there isn't an author (note as author requirement is
- // enforced at service level, if no author is needed then reputation
- // filtering is optional)
bool noAuthor = syncItem->authorId.isNull();
#ifdef NXS_NET_DEBUG_1
GXSNETDEBUG_PG(item->PeerId(),grpId) << ", reqlist size=" << reqListSize << ", message not present." ;
#endif
// grp meta must be present if author present
+
if(!noAuthor && grpMeta == NULL)
{
#ifdef NXS_NET_DEBUG_1
@@ -2828,7 +2825,14 @@ void RsGxsNetService::locked_genReqMsgTransaction(NxsTransaction* tr)
continue;
}
- if(rsIdentity && rsIdentity->isBanned(syncItem->authorId))
+ // The algorithm on request of message is:
+ //
+ // - always re-check for author ban level
+ // - if author is locally banned, do not download.
+ // - if author is not locally banned, download, whatever friends' opinion might be.
+
+#warning Update the code below to correctly send/recv dependign on reputation
+ if(rsIdentity && rsIdentity->overallReputationLevel(syncItem->authorId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
{
#ifdef NXS_NET_DEBUG_1
GXSNETDEBUG_PG(item->PeerId(),grpId) << ", Identity " << syncItem->authorId << " is banned. Not requesting message!" << std::endl;
@@ -2844,7 +2848,7 @@ void RsGxsNetService::locked_genReqMsgTransaction(NxsTransaction* tr)
continue ;
}
-
+#ifdef TO_BE_REMOVED
if(mReputations->haveReputation(syncItem->authorId) || noAuthor)
{
GixsReputation rep;
@@ -2859,17 +2863,20 @@ void RsGxsNetService::locked_genReqMsgTransaction(NxsTransaction* tr)
// at genexchange side of things
if(rep.score >= (int)grpMeta->mReputationCutOff || noAuthor)
{
-#ifdef NXS_NET_DEBUG_1
- GXSNETDEBUG_PG(item->PeerId(),grpId) << ", passed! Adding message to req list." << std::endl;
#endif
- RsNxsSyncMsgItem* msgItem = new RsNxsSyncMsgItem(mServType);
- msgItem->grpId = grpId;
- msgItem->msgId = msgId;
- msgItem->flag = RsNxsSyncMsgItem::FLAG_REQUEST;
- msgItem->transactionNumber = transN;
- msgItem->PeerId(peerFrom);
- reqList.push_back(msgItem);
- ++reqListSize ;
+#ifdef NXS_NET_DEBUG_1
+ GXSNETDEBUG_PG(item->PeerId(),grpId) << ", passed! Adding message to req list." << std::endl;
+#endif
+ RsNxsSyncMsgItem* msgItem = new RsNxsSyncMsgItem(mServType);
+ msgItem->grpId = grpId;
+ msgItem->msgId = msgId;
+ msgItem->flag = RsNxsSyncMsgItem::FLAG_REQUEST;
+ msgItem->transactionNumber = transN;
+ msgItem->PeerId(peerFrom);
+ reqList.push_back(msgItem);
+ ++reqListSize ;
+
+#ifdef TO_BE_REMOVED
}
#ifdef NXS_NET_DEBUG_1
else
@@ -2889,6 +2896,7 @@ void RsGxsNetService::locked_genReqMsgTransaction(NxsTransaction* tr)
entry.mMsgId = syncItem->msgId;
toVet.push_back(entry);
}
+#endif
}
#ifdef NXS_NET_DEBUG_1
else
@@ -3061,13 +3069,14 @@ void RsGxsNetService::locked_genReqGrpTransaction(NxsTransaction* tr)
}
// FIXTESTS global variable rsReputations not available in unittests!
- if(!grpSyncItem->authorId.isNull() && rsIdentity && rsIdentity->isBanned(grpSyncItem->authorId))
- {
+#warning Update the code below to correctly send/recv dependign on reputation
+ if(!grpSyncItem->authorId.isNull() && rsIdentity && rsIdentity->overallReputationLevel(grpSyncItem->authorId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
+ {
#ifdef NXS_NET_DEBUG_0
- GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << " Identity " << grpSyncItem->authorId << " is banned. Not syncing group." << std::endl;
+ GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << " Identity " << grpSyncItem->authorId << " is banned. Not syncing group." << std::endl;
#endif
- continue ;
- }
+ continue ;
+ }
if( (mGrpAutoSync && !haveItem) || latestVersion)
{
diff --git a/libretroshare/src/gxs/rsgxsutil.cc b/libretroshare/src/gxs/rsgxsutil.cc
index 8b2b25a5d..694f34972 100644
--- a/libretroshare/src/gxs/rsgxsutil.cc
+++ b/libretroshare/src/gxs/rsgxsutil.cc
@@ -171,7 +171,7 @@ bool RsGxsIntegrityCheck::check()
GXSUTIL_DEBUG() << "TimeStamping group authors' key ID " << grp->metaData->mAuthorId << " in group ID " << grp->grpId << std::endl;
#endif
- if(rsIdentity!=NULL && !rsIdentity->isBanned(grp->metaData->mAuthorId))
+ if(rsIdentity!=NULL && rsIdentity->overallReputationLevel(grp->metaData->mAuthorId) > RsReputations::REPUTATION_LOCALLY_NEGATIVE)
used_gxs_ids.insert(std::make_pair(grp->metaData->mAuthorId,grp->grpId)) ;
}
}
@@ -269,7 +269,7 @@ bool RsGxsIntegrityCheck::check()
#ifdef DEBUG_GXSUTIL
GXSUTIL_DEBUG() << "TimeStamping message authors' key ID " << msg->metaData->mAuthorId << " in message " << msg->msgId << ", group ID " << msg->grpId<< std::endl;
#endif
- if(rsIdentity!=NULL && !rsIdentity->isBanned(msg->metaData->mAuthorId))
+ if(rsIdentity!=NULL && rsIdentity->overallReputationLevel(msg->metaData->mAuthorId) > RsReputations::REPUTATION_LOCALLY_NEGATIVE)
used_gxs_ids.insert(std::make_pair(msg->metaData->mAuthorId,msg->metaData->mGroupId)) ;
}
diff --git a/libretroshare/src/retroshare/rsidentity.h b/libretroshare/src/retroshare/rsidentity.h
index 4a48b747c..dff973204 100644
--- a/libretroshare/src/retroshare/rsidentity.h
+++ b/libretroshare/src/retroshare/rsidentity.h
@@ -184,8 +184,6 @@ public:
// Cyril: Reputation details. At some point we might want to merge information
// between the two into a single global score. Since the old reputation system
// is not finished yet, I leave this in place. We should decide what to do with it.
-#warning (cyril) possibly remove this old reputation field.
- GxsReputation mReputation_oldSystem; // this is the old "mReputation" field, which apparently is not used.
RsReputations::ReputationInfo mReputation;
// avatar
@@ -255,7 +253,14 @@ public:
virtual bool setAsRegularContact(const RsGxsId& id,bool is_a_contact) = 0 ;
virtual bool isARegularContact(const RsGxsId& id) = 0 ;
- virtual bool isBanned(const RsGxsId& id) =0;
+
+ /*!
+ * \brief overallReputationLevel
+ * Returns the overall reputation level of the supplied identity. See rsreputations.h
+ * \param id
+ * \return
+ */
+ virtual RsReputations::ReputationLevel overallReputationLevel(const RsGxsId& id)=0;
virtual time_t getLastUsageTS(const RsGxsId &id) =0;
// Specific RsIdentity Functions....
diff --git a/libretroshare/src/retroshare/rsreputations.h b/libretroshare/src/retroshare/rsreputations.h
index dac28ad38..ce8e46401 100644
--- a/libretroshare/src/retroshare/rsreputations.h
+++ b/libretroshare/src/retroshare/rsreputations.h
@@ -36,17 +36,27 @@ public:
// This is the interface file for the reputation system
//
- enum Opinion { OPINION_NEGATIVE = 0, OPINION_NEUTRAL = 1, OPINION_POSITIVE = 2 } ;
- enum Assessment { ASSESSMENT_BAD = 0, ASSESSMENT_OK = 1 } ;
+ enum Opinion { OPINION_NEGATIVE = 0, OPINION_NEUTRAL = 1, OPINION_POSITIVE = 2 } ;
+
+ enum ReputationLevel { REPUTATION_LOCALLY_NEGATIVE = 0x00, // local opinion is positive
+ REPUTATION_REMOTELY_NEGATIVE = 0x01, // local opinion is neutral and friends are positive in average
+ REPUTATION_NEUTRAL = 0x02, // no reputation information ;
+ REPUTATION_REMOTELY_POSITIVE = 0x03, // local opinion is neutral and friends are negative in average
+ REPUTATION_LOCALLY_POSITIVE = 0x04 // local opinion is negative
+ };
struct ReputationInfo
{
- ReputationInfo() : mOwnOpinion(OPINION_NEUTRAL), mOverallReputationScore(REPUTATION_THRESHOLD_DEFAULT), mFriendAverage(REPUTATION_THRESHOLD_DEFAULT),mAssessment(ASSESSMENT_OK){}
+ ReputationInfo() : mOwnOpinion(OPINION_NEUTRAL), mFriendAverageScore(REPUTATION_THRESHOLD_DEFAULT),mOverallReputationLevel(REPUTATION_NEUTRAL){}
RsReputations::Opinion mOwnOpinion ;
- float mOverallReputationScore ;
- float mFriendAverage ;
- RsReputations::Assessment mAssessment; // this should help clients in taking decisions
+
+ uint32_t mFriendsPositiveVotes ;
+ uint32_t mFriendsNegativeVotes ;
+
+ float mFriendAverageScore ;
+
+ RsReputations::ReputationLevel mOverallReputationLevel; // this should help clients in taking decisions
};
virtual bool setOwnOpinion(const RsGxsId& key_id, const Opinion& op) =0;
diff --git a/libretroshare/src/services/p3gxsreputation.cc b/libretroshare/src/services/p3gxsreputation.cc
index 68933e4a8..f47dd6f2c 100644
--- a/libretroshare/src/services/p3gxsreputation.cc
+++ b/libretroshare/src/services/p3gxsreputation.cc
@@ -795,8 +795,9 @@ bool p3GxsReputation::getReputationInfo(const RsGxsId& gxsid, const RsPgpId& own
if(it == mReputations.end())
{
info.mOwnOpinion = RsReputations::OPINION_NEUTRAL ;
- info.mOverallReputationScore = RsReputations::REPUTATION_THRESHOLD_DEFAULT ;
- info.mFriendAverage = REPUTATION_THRESHOLD_DEFAULT ;
+ info.mFriendAverageScore = REPUTATION_THRESHOLD_DEFAULT ;
+ info.mFriendsNegativeVotes = 0 ;
+ info.mFriendsPositiveVotes = 0 ;
owner_id = ownerNode ;
}
@@ -805,8 +806,9 @@ bool p3GxsReputation::getReputationInfo(const RsGxsId& gxsid, const RsPgpId& own
Reputation& rep(it->second) ;
info.mOwnOpinion = RsReputations::Opinion(rep.mOwnOpinion) ;
- info.mOverallReputationScore = rep.mReputation ;
- info.mFriendAverage = rep.mFriendAverage ;
+ info.mFriendAverageScore = rep.mFriendAverage ;
+ info.mFriendsNegativeVotes = rep.mFriendsNegative ;
+ info.mFriendsPositiveVotes = rep.mFriendsPositive ;
if(rep.mOwnerNode.isNull())
rep.mOwnerNode = ownerNode ;
@@ -814,33 +816,67 @@ bool p3GxsReputation::getReputationInfo(const RsGxsId& gxsid, const RsPgpId& own
owner_id = rep.mOwnerNode ;
}
+ // now compute overall score and reputation
+
+ // 0 - check for own opinion. If positive or negative, it decides on the result
+
+ if(info.mOwnOpinion == RsReputations::OPINION_NEGATIVE)
+ {
+ // own opinion is always read in priority
+
+ info.mOverallReputationLevel = RsReputations::REPUTATION_LOCALLY_NEGATIVE ;
+ return true ;
+ }
+ if(info.mOwnOpinion == RsReputations::OPINION_POSITIVE)
+ {
+ // own opinion is always read in priority
+
+ info.mOverallReputationLevel = RsReputations::REPUTATION_LOCALLY_POSITIVE ;
+ return true ;
+ }
+
+ // 1 - check for banned PGP ids.
+
std::map::iterator it2 ;
if(!owner_id.isNull() && (it2 = mBannedPgpIds.find(owner_id))!=mBannedPgpIds.end())
{
+ // Check if current identity is present in the list of known identities for this banned node.
+
if(it2->second.known_identities.find(gxsid) == it2->second.known_identities.end())
{
it2->second.known_identities.insert(gxsid) ;
it2->second.last_activity_TS = now ;
+
+ // if so, update
+
mBannedNodesProxyNeedsUpdate = true ;
}
- info.mAssessment = RsReputations::ASSESSMENT_BAD ;
#ifdef DEBUG_REPUTATION2
std::cerr << "p3GxsReputations: identity " << gxsid << " is banned because owner node ID " << owner_id << " is banned (found in banned nodes list)." << std::endl;
#endif
+ info.mOverallReputationLevel = RsReputations::REPUTATION_LOCALLY_NEGATIVE ;
+ return true ;
}
- else if(mPerNodeBannedIdsProxy.find(gxsid) != mPerNodeBannedIdsProxy.end())
+ // also check the proxy
+
+ if(mPerNodeBannedIdsProxy.find(gxsid) != mPerNodeBannedIdsProxy.end())
{
#ifdef DEBUG_REPUTATION2
std::cerr << "p3GxsReputations: identity " << gxsid << " is banned because owner node ID " << owner_id << " is banned (found in proxy)." << std::endl;
#endif
- info.mAssessment = RsReputations::ASSESSMENT_BAD ;
+ info.mOverallReputationLevel = RsReputations::REPUTATION_LOCALLY_NEGATIVE ;
+ return true;
}
- else if(info.mOverallReputationScore <= mAutoBanIdentitiesLimit)
- info.mAssessment = RsReputations::ASSESSMENT_BAD ;
+ // 2 - now, our own opinion is neutral, which means we rely on what our friends tell
+
+ if(info.mFriendsPositiveVotes > info.mFriendsNegativeVotes)
+ info.mOverallReputationLevel = RsReputations::REPUTATION_REMOTELY_POSITIVE ;
+ else if(info.mFriendsPositiveVotes < info.mFriendsNegativeVotes)
+ info.mOverallReputationLevel = RsReputations::REPUTATION_REMOTELY_NEGATIVE ;
else
- info.mAssessment = RsReputations::ASSESSMENT_OK ;
+ info.mOverallReputationLevel = RsReputations::REPUTATION_NEUTRAL ;
#ifdef DEBUG_REPUTATION2
std::cerr << " information present. OwnOp = " << info.mOwnOpinion << ", owner node=" << owner_id << ", overall score=" << info.mAssessment << std::endl;
@@ -887,7 +923,7 @@ bool p3GxsReputation::isIdentityBanned(const RsGxsId &id)
#ifdef DEBUG_REPUTATION
std::cerr << "isIdentityBanned(): returning " << (info.mAssessment == RsReputations::ASSESSMENT_BAD) << " for GXS id " << id << std::endl;
#endif
- return info.mAssessment == RsReputations::ASSESSMENT_BAD ;
+ return info.mOverallReputationLevel == RsReputations::REPUTATION_LOCALLY_NEGATIVE ;
}
bool p3GxsReputation::setOwnOpinion(const RsGxsId& gxsid, const RsReputations::Opinion& opinion)
@@ -1292,11 +1328,22 @@ void Reputation::updateReputation()
int friend_total = 0;
+ mFriendsNegative = 0 ;
+ mFriendsPositive = 0 ;
+
// accounts for all friends. Neutral opinions count for 1-1=0
// because the average is performed over only accessible peers (not the total number) we need to shift to 1
for(std::map::const_iterator it(mOpinions.begin());it!=mOpinions.end();++it)
+ {
+ if(it->second == RsReputations::OPINION_NEGATIVE)
+ ++mFriendsNegative ;
+
+ if(it->second == RsReputations::OPINION_POSITIVE)
+ ++mFriendsPositive ;
+
friend_total += it->second - 1;
+ }
if(mOpinions.empty()) // includes the case of no friends!
mFriendAverage = 1.0f ;
@@ -1351,9 +1398,9 @@ void Reputation::updateReputation()
// now compute a bias for PGP-signed ids.
if(mOwnOpinion == RsReputations::OPINION_NEUTRAL)
- mReputation = mFriendAverage ;
+ mReputationScore = mFriendAverage ;
else
- mReputation = (float)mOwnOpinion ;
+ mReputationScore = (float)mOwnOpinion ;
}
void p3GxsReputation::debug_print()
@@ -1366,7 +1413,7 @@ void p3GxsReputation::debug_print()
for(std::map::const_iterator it(mReputations.begin());it!=mReputations.end();++it)
{
- std::cerr << " " << it->first << ": own: " << it->second.mOwnOpinion << ", Friend average: " << it->second.mFriendAverage << ", global_score: " << it->second.mReputation
+ std::cerr << " " << it->first << ": own: " << it->second.mOwnOpinion << ", Friend average: " << it->second.mFriendAverage << ", global_score: " << it->second.mReputationScore
<< ", last own update: " << now - it->second.mOwnOpinionTs << " secs ago." << std::endl;
#ifdef DEBUG_REPUTATION2
for(std::map::const_iterator it2(it->second.mOpinions.begin());it2!=it->second.mOpinions.end();++it2)
diff --git a/libretroshare/src/services/p3gxsreputation.h b/libretroshare/src/services/p3gxsreputation.h
index 94fb356e1..8016ed48d 100644
--- a/libretroshare/src/services/p3gxsreputation.h
+++ b/libretroshare/src/services/p3gxsreputation.h
@@ -69,10 +69,10 @@ class Reputation
{
public:
Reputation()
- :mOwnOpinion(RsReputations::OPINION_NEUTRAL), mOwnOpinionTs(0),mFriendAverage(1.0f), mReputation(RsReputations::OPINION_NEUTRAL),mIdentityFlags(REPUTATION_IDENTITY_FLAG_NEEDS_UPDATE){ }
+ :mOwnOpinion(RsReputations::OPINION_NEUTRAL), mOwnOpinionTs(0),mFriendAverage(1.0f), mReputationScore(RsReputations::OPINION_NEUTRAL),mIdentityFlags(REPUTATION_IDENTITY_FLAG_NEEDS_UPDATE){ }
Reputation(const RsGxsId& /*about*/)
- :mOwnOpinion(RsReputations::OPINION_NEUTRAL), mOwnOpinionTs(0),mFriendAverage(1.0f), mReputation(RsReputations::OPINION_NEUTRAL),mIdentityFlags(REPUTATION_IDENTITY_FLAG_NEEDS_UPDATE){ }
+ :mOwnOpinion(RsReputations::OPINION_NEUTRAL), mOwnOpinionTs(0),mFriendAverage(1.0f), mReputationScore(RsReputations::OPINION_NEUTRAL),mIdentityFlags(REPUTATION_IDENTITY_FLAG_NEEDS_UPDATE){ }
void updateReputation();
@@ -80,12 +80,15 @@ public:
int32_t mOwnOpinion;
time_t mOwnOpinionTs;
- float mFriendAverage ;
- float mReputation;
-
- RsPgpId mOwnerNode;
+ float mFriendAverage ;
+ uint32_t mFriendsPositive ; // number of positive vites from friends
+ uint32_t mFriendsNegative ; // number of negative vites from friends
+
+ float mReputationScore;
+
+ RsPgpId mOwnerNode;
- uint32_t mIdentityFlags;
+ uint32_t mIdentityFlags;
};
diff --git a/libretroshare/src/services/p3idservice.cc b/libretroshare/src/services/p3idservice.cc
index 72cd3231e..d0154be6e 100644
--- a/libretroshare/src/services/p3idservice.cc
+++ b/libretroshare/src/services/p3idservice.cc
@@ -607,15 +607,12 @@ bool p3IdService::getIdDetails(const RsGxsId &id, RsIdentityDetails &details)
return false;
}
-bool p3IdService::isBanned(const RsGxsId &id)
+RsReputations::ReputationLevel p3IdService::overallReputationLevel(const RsGxsId &id)
{
RsIdentityDetails det ;
getIdDetails(id,det) ;
-#ifdef DEBUG_REPUTATION
- std::cerr << "isIdentityBanned(): returning " << (det.mReputation.mAssessment == RsReputations::ASSESSMENT_BAD) << " for GXS id " << id << std::endl;
-#endif
- return det.mReputation.mAssessment == RsReputations::ASSESSMENT_BAD ;
+ return det.mReputation.mOverallReputationLevel ;
}
bool p3IdService::isOwnId(const RsGxsId& id)
@@ -810,7 +807,7 @@ bool p3IdService::requestKey(const RsGxsId &id, const std::list& peers
RsReputations::ReputationInfo info ;
rsReputations->getReputationInfo(id,RsPgpId(),info) ;
- if(info.mAssessment == RsReputations::ASSESSMENT_BAD)
+ if(info.mOverallReputationLevel == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
{
std::cerr << "(II) not requesting Key " << id << " because it has been banned." << std::endl;
diff --git a/libretroshare/src/services/p3idservice.h b/libretroshare/src/services/p3idservice.h
index 5ca5d1c75..638a9d2e0 100644
--- a/libretroshare/src/services/p3idservice.h
+++ b/libretroshare/src/services/p3idservice.h
@@ -274,7 +274,7 @@ public:
virtual bool setAsRegularContact(const RsGxsId& id,bool is_a_contact) ;
virtual bool isARegularContact(const RsGxsId& id) ;
- virtual bool isBanned(const RsGxsId& id) ;
+ virtual RsReputations::ReputationLevel overallReputationLevel(const RsGxsId& id);
virtual time_t getLastUsageTS(const RsGxsId &id) ;
/**************** RsGixs Implementation ***************/
diff --git a/retroshare-gui/src/gui/Identity/IdDetailsDialog.cpp b/retroshare-gui/src/gui/Identity/IdDetailsDialog.cpp
index f1419b650..a988a8563 100644
--- a/retroshare-gui/src/gui/Identity/IdDetailsDialog.cpp
+++ b/retroshare-gui/src/gui/Identity/IdDetailsDialog.cpp
@@ -264,10 +264,9 @@ void IdDetailsDialog::insertIdDetails(uint32_t token)
RsReputations::ReputationInfo info ;
rsReputations->getReputationInfo(RsGxsId(data.mMeta.mGroupId),data.mPgpId,info) ;
- ui->neighborNodesOpinion_TF->setText(QString::number(info.mOverallReputationScore-1.0f));
-
- ui->overallOpinion_TF->setText(QString::number(info.mOverallReputationScore-1.0f) +" ("+
- ((info.mAssessment == RsReputations::ASSESSMENT_OK)? tr("OK") : tr("Banned")) +")" ) ;
+#warning (csoler) Do we need to do this? This code is apparently not used.
+ ui->neighborNodesOpinion_TF->setText(QString::number(info.mFriendAverageScore));
+ ui->overallOpinion_TF->setText(QString::number(info.mOverallReputationLevel));
switch(info.mOwnOpinion)
{
diff --git a/retroshare-gui/src/gui/Identity/IdDialog.cpp b/retroshare-gui/src/gui/Identity/IdDialog.cpp
index 5f7a20010..67025fff5 100644
--- a/retroshare-gui/src/gui/Identity/IdDialog.cpp
+++ b/retroshare-gui/src/gui/Identity/IdDialog.cpp
@@ -1392,7 +1392,8 @@ bool IdDialog::fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item,
bool isOwnId = (data.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN);
RsIdentityDetails idd ;
rsIdentity->getIdDetails(RsGxsId(data.mMeta.mGroupId),idd) ;
- bool isBanned = idd.mReputation.mAssessment == RsReputations::ASSESSMENT_BAD;
+
+ bool isBanned = idd.mReputation.mOverallReputationLevel == RsReputations::REPUTATION_LOCALLY_NEGATIVE;
uint32_t item_flags = 0 ;
/* do filtering */
@@ -1462,7 +1463,7 @@ bool IdDialog::fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item,
item->setData(RSID_COL_KEYID, Qt::UserRole,QVariant(item_flags)) ;
item->setTextAlignment(RSID_COL_VOTES, Qt::AlignRight | Qt::AlignVCenter);
- item->setData(RSID_COL_VOTES,Qt::DisplayRole, QString::number(idd.mReputation.mOverallReputationScore - 1.0f,'f',3));
+ item->setData(RSID_COL_VOTES,Qt::DisplayRole, idd.mReputation.mOverallReputationLevel);
if(isOwnId)
{
@@ -1836,10 +1837,24 @@ void IdDialog::insertIdDetails(uint32_t token)
RsReputations::ReputationInfo info ;
rsReputations->getReputationInfo(RsGxsId(data.mMeta.mGroupId),data.mPgpId,info) ;
- ui->neighborNodesOpinion_TF->setText(QString::number(info.mFriendAverage - 1.0f));
+ QString frep_string ;
+ if(info.mFriendsPositiveVotes > 0) frep_string += QString::number(info.mFriendsPositiveVotes) + tr(" positive, ") ;
+ if(info.mFriendsNegativeVotes > 0) frep_string += QString::number(info.mFriendsNegativeVotes) + tr(" negative, ") ;
- ui->overallOpinion_TF->setText(QString::number(info.mOverallReputationScore - 1.0f) +" ("+
- ((info.mAssessment == RsReputations::ASSESSMENT_OK)? tr("OK") : tr("Banned")) +")" ) ;
+ if(info.mFriendsPositiveVotes==0 && info.mFriendsNegativeVotes==0)
+ frep_string = tr("No votes from friends, ") ;
+
+ ui->neighborNodesOpinion_TF->setText(frep_string) ;
+
+ switch(info.mOverallReputationLevel)
+ {
+ case RsReputations::REPUTATION_LOCALLY_POSITIVE: ui->overallOpinion_TF->setText(tr("Positive")) ; break ;
+ case RsReputations::REPUTATION_LOCALLY_NEGATIVE: ui->overallOpinion_TF->setText(tr("Negative (Banned)")) ; break ;
+ case RsReputations::REPUTATION_REMOTELY_POSITIVE: ui->overallOpinion_TF->setText(tr("Positive, according to your friends")) ; break ;
+ case RsReputations::REPUTATION_REMOTELY_NEGATIVE: ui->overallOpinion_TF->setText(tr("Negative, according to your friends")) ; break ;
+ default:
+ case RsReputations::REPUTATION_NEUTRAL: ui->overallOpinion_TF->setText(tr("Neutral")) ; break ;
+ }
switch(info.mOwnOpinion)
{
diff --git a/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp b/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp
index 5c7d00dd7..3fee9346c 100644
--- a/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp
+++ b/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp
@@ -904,7 +904,7 @@ bool GxsIdDetails::MakeIdDesc(const RsGxsId &id, bool doIcons, QString &str, QLi
QString GxsIdDetails::getName(const RsIdentityDetails &details)
{
- if(rsIdentity->isBanned(details.mId))
+ if(details.mReputation.mOverallReputationLevel == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
return tr("[Banned]") ;
QString name = QString::fromUtf8(details.mNickname.c_str()).left(RSID_MAXIMUM_NICKNAME_SIZE);
@@ -923,7 +923,7 @@ QString GxsIdDetails::getComment(const RsIdentityDetails &details)
QString comment;
QString nickname ;
- bool banned = rsIdentity->isBanned(details.mId) ;
+ bool banned = (details.mReputation.mOverallReputationLevel == RsReputations::REPUTATION_LOCALLY_NEGATIVE);
if(details.mNickname.empty())
nickname = tr("[Unknown]") ;
@@ -962,7 +962,7 @@ void GxsIdDetails::getIcons(const RsIdentityDetails &details, QList &icon
{
QPixmap pix ;
- if(rsIdentity->isBanned(details.mId))
+ if(details.mReputation.mOverallReputationLevel == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
{
icons.clear() ;
icons.push_back(QIcon(IMAGE_BANNED)) ;
diff --git a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp
index 0177f892f..aa5edc91e 100644
--- a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp
+++ b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp
@@ -116,14 +116,14 @@ void GxsIdRSTreeWidgetItem::setId(const RsGxsId &id, int column, bool retryWhenF
void GxsIdRSTreeWidgetItem::updateBannedState()
{
- if(mBannedState != rsIdentity->isBanned(mId))
+ if(mBannedState != (rsIdentity->overallReputationLevel(mId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE))
forceUpdate() ;
}
void GxsIdRSTreeWidgetItem::forceUpdate()
{
mIdFound = false;
- mBannedState = rsIdentity->isBanned(mId) ;
+ mBannedState = (rsIdentity->overallReputationLevel(mId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE);
startProcess();
}
@@ -169,7 +169,7 @@ QVariant GxsIdRSTreeWidgetItem::data(int column, int role) const
if(mId.isNull())
return RSTreeWidgetItem::data(column, role);
- else if(rsIdentity->isBanned(mId))
+ else if(rsIdentity->overallReputationLevel(mId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
pix = QImage(BANNED_IMAGE) ;
else if (mAvatar.mSize == 0 || !pix.loadFromData(mAvatar.mData, mAvatar.mSize, "PNG"))
pix = GxsIdDetails::makeDefaultIcon(mId);
diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp
index 8dea116fe..8bf70fe48 100644
--- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp
+++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp
@@ -996,13 +996,13 @@ QTreeWidgetItem *GxsForumThreadWidget::convertMsgToThreadWidget(const RsGxsForum
// Early check for a message that should be hidden because its author
// is flagged with a bad reputation
+ uint32_t reputation_level = rsIdentity->overallReputationLevel(msg.mMeta.mAuthorId) ;
- bool redacted = rsIdentity->isBanned(msg.mMeta.mAuthorId) ;
+ bool redacted = (reputation_level == RsReputations::REPUTATION_LOCALLY_NEGATIVE) ;
GxsIdRSTreeWidgetItem *item = new GxsIdRSTreeWidgetItem(mThreadCompareRole,GxsIdDetails::ICON_TYPE_ALL || (redacted?(GxsIdDetails::ICON_TYPE_REDACTED):0));
item->moveToThread(ui->threadTreeWidget->thread());
-
if(redacted)
item->setText(COLUMN_THREAD_TITLE, tr("[ ... Redacted message ... ]"));
else
@@ -1431,7 +1431,8 @@ void GxsForumThreadWidget::insertMessageData(const RsGxsForumMsg &msg)
return;
}
- bool redacted = rsIdentity->isBanned(msg.mMeta.mAuthorId) ;
+ uint32_t overall_reputation = rsIdentity->overallReputationLevel(msg.mMeta.mAuthorId) ;
+ bool redacted = (overall_reputation == RsReputations::REPUTATION_LOCALLY_NEGATIVE) ;
mStateHelper->setActive(mTokenTypeMessageData, true);
From e5e59098ac3a09f208d85bb6e4b54e5a59c6a007 Mon Sep 17 00:00:00 2001
From: csoler
Date: Fri, 23 Dec 2016 22:53:57 +0100
Subject: [PATCH 06/23] added proper display of reputation as an icon in
IDDialog
---
retroshare-gui/src/gui/Identity/IdDialog.cpp | 69 +++-
retroshare-gui/src/gui/Identity/IdDialog.ui | 2 +-
retroshare-gui/src/gui/icons.qrc | 366 +++++++++++-------
.../icons/bullet_green_yellow_star_128.png | Bin 0 -> 15443 bytes
.../src/gui/icons/red_biohazard64.png | Bin 0 -> 10084 bytes
.../src/gui/icons/yellow_biohazard64.png | Bin 10182 -> 10182 bytes
6 files changed, 287 insertions(+), 150 deletions(-)
create mode 100644 retroshare-gui/src/gui/icons/bullet_green_yellow_star_128.png
create mode 100644 retroshare-gui/src/gui/icons/red_biohazard64.png
diff --git a/retroshare-gui/src/gui/Identity/IdDialog.cpp b/retroshare-gui/src/gui/Identity/IdDialog.cpp
index 67025fff5..636329ebd 100644
--- a/retroshare-gui/src/gui/Identity/IdDialog.cpp
+++ b/retroshare-gui/src/gui/Identity/IdDialog.cpp
@@ -26,6 +26,8 @@
#include
#include
#include
+#include
+#include
#include "IdDialog.h"
#include "ui_IdDialog.h"
@@ -104,6 +106,12 @@
#define IMAGE_ADMIN ":/icons/bullet_blue_128.png"
#define IMAGE_INFO ":/images/info16.png"
+#define REPUTATION_LOCALLY_POSITIVE_ICON ":/icons/bullet_green_yellow_star_128.png"
+#define REPUTATION_REMOTELY_POSITIVE_ICON ":/icons/bullet_green_128.png"
+#define REPUTATION_NEUTRAL_ICON ":/icons/bullet_grey_128.png"
+#define REPUTATION_REMOTELY_NEGATIVE_ICON ":/icons/yellow_biohazard64.png"
+#define REPUTATION_LOCALLY_NEGATIVE_ICON ":/icons/red_biohazard64.png"
+
// comment this out in order to remove the sorting of circles into "belong to" and "other visible circles"
#define CIRCLE_MEMBERSHIP_CATEGORIES 1
@@ -127,6 +135,54 @@ class TreeWidgetItem : public QTreeWidgetItem {
}
}
};
+
+// This class allows to draw the item in the share flags column using an appropriate size
+
+class ReputationItemDelegate: public QStyledItemDelegate
+{
+public:
+ ReputationItemDelegate() {}
+
+ virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+ {
+ Q_ASSERT(index.isValid());
+
+ QStyleOptionViewItemV4 opt = option;
+ initStyleOption(&opt, index);
+ // disable default icon
+ opt.icon = QIcon();
+ // draw default item
+ QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter, 0);
+
+ const QRect r = option.rect;
+
+ // get pixmap
+ unsigned int icon_index = qvariant_cast(index.data(Qt::DecorationRole));
+
+ if(icon_index > 4)
+ return ;
+
+ QIcon icon ;
+
+ switch(icon_index)
+ {
+ case RsReputations::REPUTATION_LOCALLY_NEGATIVE: icon = QIcon(REPUTATION_LOCALLY_NEGATIVE_ICON) ; break ;
+ case RsReputations::REPUTATION_LOCALLY_POSITIVE: icon = QIcon(REPUTATION_LOCALLY_POSITIVE_ICON) ; break ;
+ case RsReputations::REPUTATION_REMOTELY_POSITIVE: icon = QIcon(REPUTATION_REMOTELY_POSITIVE_ICON) ; break ;
+ case RsReputations::REPUTATION_REMOTELY_NEGATIVE: icon = QIcon(REPUTATION_REMOTELY_NEGATIVE_ICON) ; break ;
+ case RsReputations::REPUTATION_NEUTRAL: icon = QIcon(REPUTATION_NEUTRAL_ICON) ; break ;
+ default:
+ return ; // dont draw anything
+ }
+
+ QPixmap pix = icon.pixmap(r.size());
+
+ // draw pixmap at center of item
+ const QPoint p = QPoint((r.width() - pix.width())/2, (r.height() - pix.height())/2);
+ painter->drawPixmap(r.topLeft() + p, pix);
+ }
+};
+
/** Constructor */
IdDialog::IdDialog(QWidget *parent) :
RsGxsUpdateBroadcastPage(rsIdentity, parent),
@@ -142,12 +198,15 @@ IdDialog::IdDialog(QWidget *parent) :
ownItem = new QTreeWidgetItem();
ownItem->setText(0, tr("My own identities"));
+ ownItem->setData(RSID_COL_VOTES, Qt::DecorationRole,0xff);
allItem = new QTreeWidgetItem();
allItem->setText(0, tr("All"));
+ allItem->setData(RSID_COL_VOTES, Qt::DecorationRole,0xff);
contactsItem = new QTreeWidgetItem();
contactsItem->setText(0, tr("My contacts"));
+ contactsItem->setData(RSID_COL_VOTES, Qt::DecorationRole,0xff);
ui->treeWidget_membership->clear();
@@ -318,6 +377,8 @@ IdDialog::IdDialog(QWidget *parent) :
ui->idTreeWidget->setColumnWidth(RSID_COL_IDTYPE, 18 * fontWidth);
ui->idTreeWidget->setColumnWidth(RSID_COL_VOTES, 7 * fontWidth);
+ ui->idTreeWidget->setItemDelegateForColumn(RSID_COL_VOTES,new ReputationItemDelegate()) ;
+
//QHeaderView_setSectionResizeMode(ui->idTreeWidget->header(), QHeaderView::ResizeToContents);
mIdQueue = new TokenQueue(rsIdentity->getTokenService(), this);
@@ -1463,7 +1524,7 @@ bool IdDialog::fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item,
item->setData(RSID_COL_KEYID, Qt::UserRole,QVariant(item_flags)) ;
item->setTextAlignment(RSID_COL_VOTES, Qt::AlignRight | Qt::AlignVCenter);
- item->setData(RSID_COL_VOTES,Qt::DisplayRole, idd.mReputation.mOverallReputationLevel);
+ item->setData(RSID_COL_VOTES,Qt::DecorationRole, idd.mReputation.mOverallReputationLevel);
if(isOwnId)
{
@@ -1838,11 +1899,11 @@ void IdDialog::insertIdDetails(uint32_t token)
rsReputations->getReputationInfo(RsGxsId(data.mMeta.mGroupId),data.mPgpId,info) ;
QString frep_string ;
- if(info.mFriendsPositiveVotes > 0) frep_string += QString::number(info.mFriendsPositiveVotes) + tr(" positive, ") ;
- if(info.mFriendsNegativeVotes > 0) frep_string += QString::number(info.mFriendsNegativeVotes) + tr(" negative, ") ;
+ if(info.mFriendsPositiveVotes > 0) frep_string += QString::number(info.mFriendsPositiveVotes) + tr(" positive ") ;
+ if(info.mFriendsNegativeVotes > 0) frep_string += QString::number(info.mFriendsNegativeVotes) + tr(" negative ") ;
if(info.mFriendsPositiveVotes==0 && info.mFriendsNegativeVotes==0)
- frep_string = tr("No votes from friends, ") ;
+ frep_string = tr("No votes from friends") ;
ui->neighborNodesOpinion_TF->setText(frep_string) ;
diff --git a/retroshare-gui/src/gui/Identity/IdDialog.ui b/retroshare-gui/src/gui/Identity/IdDialog.ui
index 3dceaa373..57fbc3649 100644
--- a/retroshare-gui/src/gui/Identity/IdDialog.ui
+++ b/retroshare-gui/src/gui/Identity/IdDialog.ui
@@ -492,7 +492,7 @@
-
- Neighbor nodes:
+ Friend votes:
diff --git a/retroshare-gui/src/gui/icons.qrc b/retroshare-gui/src/gui/icons.qrc
index c2506c851..1a63b784d 100644
--- a/retroshare-gui/src/gui/icons.qrc
+++ b/retroshare-gui/src/gui/icons.qrc
@@ -1,147 +1,223 @@
-
- icons/svg/profile.svg
- icons/svg/download.svg
- icons/svg/folders.svg
- icons/svg/folders1.svg
- icons/svg/magnifying-glass.svg
- icons/svg/upload.svg
- icons/settings/appearance.svg
- icons/settings/channels.svg
- icons/settings/chat.svg
- icons/settings/directories.svg
- icons/settings/filesharing.svg
- icons/settings/forums.svg
- icons/settings/general.svg
- icons/settings/messages.svg
- icons/settings/network.svg
- icons/settings/notify.svg
- icons/settings/people.svg
- icons/settings/permissions.svg
- icons/settings/plugins.svg
- icons/settings/posted.svg
- icons/settings/profile.svg
- icons/settings/server.svg
- icons/settings/sound.svg
- icons/settings/webinterface.svg
- icons/add_user_256.png
- icons/aol.png
- icons/avatar_128.png
- icons/avatar_grey_128.png
- icons/blank_red_128.png
- icons/void_128.png
- icons/blank_green_128.png
- icons/blank_blue_128.png
- icons/browsable_green_128.png
- icons/search_red_128.png
- icons/anonymous_blue_128.png
- icons/bullet_blue_128.png
- icons/bullet_green_128.png
- icons/bullet_grey_128.png
- icons/bullet_red_128.png
- icons/bullet_yellow_128.png
- icons/channels_128.png
- icons/channels_red_128.png
- icons/chat_128.png
- icons/chat_red_128.png
- icons/circles_128.png
- icons/circles_new_128.png
- icons/friends_128.png
- icons/global_switch_off_128.png
- icons/global_switch_on_128.png
- icons/gmail.png
- icons/help_128.png
- icons/help_64.png
- icons/information_128.png
- icons/internet_128.png
- icons/invite64.png
- icons/knews_128.png
- icons/knews_red_128.png
- icons/konversation_128.png
- icons/konversation128.png
- icons/konversation_red_128.png
- icons/ktorrent_128.png
- icons/ktorrent_red_128.png
- icons/logo_0_connected_128.png
- icons/logo_128.png
- icons/logo_1_connected_128.png
- icons/logo_2_connected_128.png
- icons/mail_128.png
- icons/mail_old_128.png
- icons/mail_red_128.png
- icons/newsfeed128.png
- icons/outlook.png
- icons/plugins_128.png
- icons/posted_128.png
- icons/posted_red_128.png
- icons/quit_128.png
- icons/security_high_128.png
- icons/security_low_128.png
- icons/security_medium_128.png
- icons/star_overlay_128.png
- icons/switch00_128.png
- icons/switch01_128.png
- icons/switch10_128.png
- icons/switch11_128.png
- icons/system_128.png
- icons/tile_checking_48.png
- icons/tile_downloaded_48.png
- icons/tile_downloading_48.png
- icons/tile_inactive_48.png
- icons/tor-logo.png
- icons/tor-off.png
- icons/tor-on.png
- icons/tor-starting.png
- icons/tor-stopping.png
- icons/user-away_64.png
- icons/user-away-extended_64.png
- icons/user-busy_64.png
- icons/user-offline_64.png
- icons/user-online_64.png
- icons/yahoo.png
- icons/yandex.png
- icons/yellow_biohazard64.png
- icons/png/attach.png
- icons/png/attach-image.png
- icons/png/highlight.png
- icons/png/invite.png
- icons/png/leave.png
- icons/png/search.png
- icons/png/send-message.png
- icons/png/settings.png
- icons/png/smiley.png
- icons/png/font.png
- icons/png/send-message-blocked.png
- icons/png/chat-bubble-notify.png
- icons/png/channels.png
- icons/png/chat-lobbies.png
- icons/png/forums.png
- icons/png/info.png
- icons/png/messages.png
- icons/png/network.png
- icons/png/newsfeed.png
- icons/png/people.png
- icons/png/posted.png
- icons/png/exit.png
- icons/png/options.png
- icons/png/filesharing.png
- icons/png/channels-notify.png
- icons/png/chat-lobbies-notify.png
- icons/png/forums-notify.png
- icons/png/messages-notify.png
- icons/png/network-notify.png
- icons/png/newsfeed-notify.png
- icons/png/people-notify.png
- icons/png/posted-notify.png
- icons/png/filesharing-notify.png
- icons/png/thumbs-up.png
- icons/png/thumbs-down.png
- icons/png/thumbs-neutral.png
- icons/png/add.png
- icons/png/netgraph.png
- icons/png/network-puplic.png
- icons/png/circles.png
- icons/png/person.png
- icons/png/keyring.png
-
+
+ icons/add_user_256.png
+ icons/anonymous_blue_128.png
+ icons/anonymous_green_128.png
+ icons/aol.png
+ icons/avatar_128.png
+ icons/avatar_grey_128.png
+ icons/blank_blue_128.png
+ icons/blank_green_128.png
+ icons/blank_red_128.png
+ icons/browsable_blue_128.png
+ icons/browsable_green_128.png
+ icons/bullet_blue_128.png
+ icons/bullet_green_128.png
+ icons/bullet_green_yellow_star_128.png
+ icons/bullet_grey_128.png
+ icons/bullet_red_128.png
+ icons/bullet_yellow_128.png
+ icons/channels_128.png
+ icons/channels_red_128.png
+ icons/chat_128.png
+ icons/chat_red_128.png
+ icons/circles_128.png
+ icons/circles_new_128.png
+ icons/friends_128.png
+ icons/global_switch_off_128.png
+ icons/global_switch_on_128.png
+ icons/gmail.png
+ icons/help_128.png
+ icons/help_64.png
+ icons/information_128.png
+ icons/internet_128.png
+ icons/invite64.png
+ icons/knews_128.png
+ icons/knews_red_128.png
+ icons/konversation_128.png
+ icons/konversation128.png
+ icons/konversation_red_128.png
+ icons/ktorrent_128.png
+ icons/ktorrent_red_128.png
+ icons/logo_0_connected_128.png
+ icons/logo_128.png
+ icons/logo_1_connected_128.png
+ icons/logo_2_connected_128.png
+ icons/mail_128.png
+ icons/mail_old_128.png
+ icons/mail_red_128.png
+ icons/newsfeed128.png
+ icons/outlook.png
+ icons/plugins_128.png
+ icons/png/add.png
+ icons/png/attach-image.png
+ icons/png/attach.png
+ icons/png/channels-notify.png
+ icons/png/channels.png
+ icons/png/chat-bubble-notify.png
+ icons/png/chat-bubble.png
+ icons/png/chat-lobbies-notify.png
+ icons/png/chat-lobbies.png
+ icons/png/circles.png
+ icons/png/empty-circle.png
+ icons/png/exit.png
+ icons/png/feedreader-notify.png
+ icons/png/feedreader.png
+ icons/png/filesharing-notify.png
+ icons/png/filesharing.png
+ icons/png/font.png
+ icons/png/forums-notify.png
+ icons/png/forums.png
+ icons/png/fullscreen_arrows.png
+ icons/png/highlight.png
+ icons/png/info.png
+ icons/png/invite.png
+ icons/png/keyring.png
+ icons/png/leave.png
+ icons/png/messages-notify.png
+ icons/png/messages.png
+ icons/png/microphone_mute.png
+ icons/png/microphone.png
+ icons/png/netgraph.png
+ icons/png/network-notify.png
+ icons/png/network.png
+ icons/png/network-puplic.png
+ icons/png/newsfeed-notify.png
+ icons/png/newsfeed.png
+ icons/png/options.png
+ icons/png/people-notify.png
+ icons/png/people.png
+ icons/png/person.png
+ icons/png/phone_hangup.png
+ icons/png/phone.png
+ icons/png/posted-notify.png
+ icons/png/posted.png
+ icons/png/search.png
+ icons/png/send-message-blocked.png
+ icons/png/send-message.png
+ icons/png/settings.png
+ icons/png/smiley.png
+ icons/png/speaker_mute.png
+ icons/png/speaker.png
+ icons/png/thumbs-down.png
+ icons/png/thumbs-neutral.png
+ icons/png/thumbs-up.png
+ icons/png/video.png
+ icons/posted_128.png
+ icons/posted_red_128.png
+ icons/quit_128.png
+ icons/red_biohazard64.png
+ icons/search_red_128.png
+ icons/security_high_128.png
+ icons/security_low_128.png
+ icons/security_medium_128.png
+ icons/settings/appearance.svg
+ icons/settings/channels.svg
+ icons/settings/chat.svg
+ icons/settings/directories.svg
+ icons/settings/filesharing.svg
+ icons/settings/forums.svg
+ icons/settings/general.svg
+ icons/settings/messages.svg
+ icons/settings/network.svg
+ icons/settings/notify.svg
+ icons/settings/people.svg
+ icons/settings/permissions.svg
+ icons/settings/plugins.svg
+ icons/settings/posted.svg
+ icons/settings/profile.svg
+ icons/settings/server.svg
+ icons/settings/sound.svg
+ icons/settings/webinterface.svg
+ icons/star_overlay_128.png
+ icons/svg/add.svg
+ icons/svg/attach-image.svg
+ icons/svg/attach.svg
+ icons/svg/channels-notify.svg
+ icons/svg/channels.svg
+ icons/svg/chat-bubble-notify.svg
+ icons/svg/chat-bubble.svg
+ icons/svg/chat-lobbies-notify.svg
+ icons/svg/chat-lobbies.svg
+ icons/svg/circles.svg
+ icons/svg/download.svg
+ icons/svg/empty-circle.svg
+ icons/svg/exit-red.svg
+ icons/svg/exit.svg
+ icons/svg/feedreader-notify.svg
+ icons/svg/feedreader.svg
+ icons/svg/filesharing-notify.svg
+ icons/svg/filesharing.svg
+ icons/svg/folders1.svg
+ icons/svg/folders.svg
+ icons/svg/font.svg
+ icons/svg/forums-notify.svg
+ icons/svg/forums.svg
+ icons/svg/fullscreen_arrows.svg
+ icons/svg/highlight.svg
+ icons/svg/info.svg
+ icons/svg/invite.svg
+ icons/svg/keyring.svg
+ icons/svg/leave.svg
+ icons/svg/magnifying-glass.svg
+ icons/svg/messages-notify.svg
+ icons/svg/messages.svg
+ icons/svg/microphone_mute.svg
+ icons/svg/microphone.svg
+ icons/svg/netgraph.svg
+ icons/svg/network-notify.svg
+ icons/svg/network-puplic.svg
+ icons/svg/network.svg
+ icons/svg/newsfeed-notify.svg
+ icons/svg/newsfeed.svg
+ icons/svg/options.svg
+ icons/svg/people-notify.svg
+ icons/svg/people.svg
+ icons/svg/person.svg
+ icons/svg/phone_hangup.svg
+ icons/svg/phone.svg
+ icons/svg/posted-notify.svg
+ icons/svg/posted.svg
+ icons/svg/profile.svg
+ icons/svg/retroshare-info.svg
+ icons/svg/retroshare-splash.svg
+ icons/svg/retroshare-symbol_black_bg.svg
+ icons/svg/retroshare-symbol_gradients.svg
+ icons/svg/retroshare-symbol-minimal.svg
+ icons/svg/search.svg
+ icons/svg/send-message-blocked.svg
+ icons/svg/send-message.svg
+ icons/svg/settings.svg
+ icons/svg/smiley.svg
+ icons/svg/speaker_mute.svg
+ icons/svg/speaker.svg
+ icons/svg/thumbs-down.svg
+ icons/svg/thumbs-neutral.svg
+ icons/svg/thumbs-up.svg
+ icons/svg/upload.svg
+ icons/svg/video.svg
+ icons/switch00_128.png
+ icons/switch01_128.png
+ icons/switch10_128.png
+ icons/switch11_128.png
+ icons/system_128.png
+ icons/tile_checking_48.png
+ icons/tile_downloaded_48.png
+ icons/tile_downloading_48.png
+ icons/tile_inactive_48.png
+ icons/tor-logo.png
+ icons/tor-off.png
+ icons/tor-on.png
+ icons/tor-starting.png
+ icons/tor-stopping.png
+ icons/user-away_64.png
+ icons/user-away-extended_64.png
+ icons/user-busy_64.png
+ icons/user-offline_64.png
+ icons/user-online_64.png
+ icons/void_128.png
+ icons/yahoo.png
+ icons/yandex.png
+ icons/yellow_biohazard64.png
+
diff --git a/retroshare-gui/src/gui/icons/bullet_green_yellow_star_128.png b/retroshare-gui/src/gui/icons/bullet_green_yellow_star_128.png
new file mode 100644
index 0000000000000000000000000000000000000000..2b49ec38414d5238c6cc21e3d634b0a0c22550c5
GIT binary patch
literal 15443
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
JPDHLkV1oRb(K7%5
literal 0
HcmV?d00001
diff --git a/retroshare-gui/src/gui/icons/red_biohazard64.png b/retroshare-gui/src/gui/icons/red_biohazard64.png
new file mode 100644
index 0000000000000000000000000000000000000000..eacbf9f8d3506cec2841648f9fc5fc9b8490fd24
GIT binary patch
literal 10084
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
literal 0
HcmV?d00001
diff --git a/retroshare-gui/src/gui/icons/yellow_biohazard64.png b/retroshare-gui/src/gui/icons/yellow_biohazard64.png
index edb6fb3f24b36b67d7267e4d0d83fdd0bbcdc876..09accbf83969471ade76ae2ef9ea0aba2f77984a 100644
GIT binary patch
delta 23
fcmX@+f6RZw8ZNE}JmR9P7IV$yTsLpy5|9M|Y%~YP
delta 23
fcmX@+f6RZw8ZNH;T%2Njns??|25#QQB_Im`ai|D>
From 873c0e60df3f6c7872f7ba8a5def6562d5605ed7 Mon Sep 17 00:00:00 2001
From: csoler
Date: Sat, 24 Dec 2016 14:13:02 +0100
Subject: [PATCH 07/23] added display of reputation in forums
---
retroshare-gui/src/gui/Identity/IdDialog.cpp | 21 ++--------------
.../src/gui/gxs/GxsCommentTreeWidget.cpp | 2 +-
retroshare-gui/src/gui/gxs/GxsIdDetails.cpp | 25 +++++++++++++++++++
retroshare-gui/src/gui/gxs/GxsIdDetails.h | 11 ++++----
.../src/gui/gxs/GxsIdTreeWidgetItem.cpp | 6 -----
.../src/gui/gxs/GxsIdTreeWidgetItem.h | 3 +--
.../gui/gxsforums/GxsForumThreadWidget.cpp | 4 +--
7 files changed, 37 insertions(+), 35 deletions(-)
diff --git a/retroshare-gui/src/gui/Identity/IdDialog.cpp b/retroshare-gui/src/gui/Identity/IdDialog.cpp
index 636329ebd..584c71d33 100644
--- a/retroshare-gui/src/gui/Identity/IdDialog.cpp
+++ b/retroshare-gui/src/gui/Identity/IdDialog.cpp
@@ -106,12 +106,6 @@
#define IMAGE_ADMIN ":/icons/bullet_blue_128.png"
#define IMAGE_INFO ":/images/info16.png"
-#define REPUTATION_LOCALLY_POSITIVE_ICON ":/icons/bullet_green_yellow_star_128.png"
-#define REPUTATION_REMOTELY_POSITIVE_ICON ":/icons/bullet_green_128.png"
-#define REPUTATION_NEUTRAL_ICON ":/icons/bullet_grey_128.png"
-#define REPUTATION_REMOTELY_NEGATIVE_ICON ":/icons/yellow_biohazard64.png"
-#define REPUTATION_LOCALLY_NEGATIVE_ICON ":/icons/red_biohazard64.png"
-
// comment this out in order to remove the sorting of circles into "belong to" and "other visible circles"
#define CIRCLE_MEMBERSHIP_CATEGORIES 1
@@ -162,18 +156,7 @@ public:
if(icon_index > 4)
return ;
- QIcon icon ;
-
- switch(icon_index)
- {
- case RsReputations::REPUTATION_LOCALLY_NEGATIVE: icon = QIcon(REPUTATION_LOCALLY_NEGATIVE_ICON) ; break ;
- case RsReputations::REPUTATION_LOCALLY_POSITIVE: icon = QIcon(REPUTATION_LOCALLY_POSITIVE_ICON) ; break ;
- case RsReputations::REPUTATION_REMOTELY_POSITIVE: icon = QIcon(REPUTATION_REMOTELY_POSITIVE_ICON) ; break ;
- case RsReputations::REPUTATION_REMOTELY_NEGATIVE: icon = QIcon(REPUTATION_REMOTELY_NEGATIVE_ICON) ; break ;
- case RsReputations::REPUTATION_NEUTRAL: icon = QIcon(REPUTATION_NEUTRAL_ICON) ; break ;
- default:
- return ; // dont draw anything
- }
+ QIcon icon = GxsIdDetails::getReputationIcon(RsReputations::ReputationLevel(icon_index));
QPixmap pix = icon.pixmap(r.size());
@@ -198,7 +181,7 @@ IdDialog::IdDialog(QWidget *parent) :
ownItem = new QTreeWidgetItem();
ownItem->setText(0, tr("My own identities"));
- ownItem->setData(RSID_COL_VOTES, Qt::DecorationRole,0xff);
+ ownItem->setData(RSID_COL_VOTES, Qt::DecorationRole,0xff); // this is in order to prevent displaying a reputaiton icon next to these items.
allItem = new QTreeWidgetItem();
allItem->setText(0, tr("All"));
diff --git a/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.cpp b/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.cpp
index 7631ad23f..2fa1f3b1e 100644
--- a/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.cpp
+++ b/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.cpp
@@ -418,7 +418,7 @@ void GxsCommentTreeWidget::service_loadThread(const uint32_t &token)
std::cerr << "GxsCommentTreeWidget::service_loadThread() Got Comment: " << comment.mMeta.mMsgId;
std::cerr << std::endl;
- GxsIdRSTreeWidgetItem *item = new GxsIdRSTreeWidgetItem(NULL) ;
+ GxsIdRSTreeWidgetItem *item = new GxsIdRSTreeWidgetItem(NULL,GxsIdDetails::ICON_TYPE_ALL) ;
QString text;
{
diff --git a/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp b/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp
index 3fee9346c..a3f4b680b 100644
--- a/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp
+++ b/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp
@@ -48,6 +48,12 @@
#define IMAGE_DEV_PATCHER ":/images/tags/dev-patcher.png"
#define IMAGE_DEV_DEVELOPER ":/images/tags/developer.png"
+#define REPUTATION_LOCALLY_POSITIVE_ICON ":/icons/bullet_green_yellow_star_128.png"
+#define REPUTATION_REMOTELY_POSITIVE_ICON ":/icons/bullet_green_128.png"
+#define REPUTATION_NEUTRAL_ICON ":/icons/bullet_grey_128.png"
+#define REPUTATION_REMOTELY_NEGATIVE_ICON ":/icons/yellow_biohazard64.png"
+#define REPUTATION_LOCALLY_NEGATIVE_ICON ":/icons/red_biohazard64.png"
+
#define TIMER_INTERVAL 500
#define MAX_ATTEMPTS 10
#define MAX_PROCESS_COUNT_PER_TIMER 50
@@ -958,6 +964,21 @@ QString nickname ;
return comment;
}
+QIcon GxsIdDetails::getReputationIcon(RsReputations::ReputationLevel icon_index)
+{
+ switch(icon_index)
+ {
+ case RsReputations::REPUTATION_LOCALLY_NEGATIVE: return QIcon(REPUTATION_LOCALLY_NEGATIVE_ICON) ; break ;
+ case RsReputations::REPUTATION_LOCALLY_POSITIVE: return QIcon(REPUTATION_LOCALLY_POSITIVE_ICON) ; break ;
+ case RsReputations::REPUTATION_REMOTELY_POSITIVE: return QIcon(REPUTATION_REMOTELY_POSITIVE_ICON) ; break ;
+ case RsReputations::REPUTATION_REMOTELY_NEGATIVE: return QIcon(REPUTATION_REMOTELY_NEGATIVE_ICON) ; break ;
+ case RsReputations::REPUTATION_NEUTRAL: return QIcon(REPUTATION_NEUTRAL_ICON) ; break ;
+ default:
+ std::cerr << "Asked for unidentified icon index " << icon_index << std::endl;
+ return QIcon(); // dont draw anything
+ }
+}
+
void GxsIdDetails::getIcons(const RsIdentityDetails &details, QList &icons,uint32_t icon_types)
{
QPixmap pix ;
@@ -969,6 +990,10 @@ void GxsIdDetails::getIcons(const RsIdentityDetails &details, QList &icon
return ;
}
+
+ if(icon_types & ICON_TYPE_REPUTATION)
+ icons.push_back(getReputationIcon(details.mReputation.mOverallReputationLevel)) ;
+
if(icon_types & ICON_TYPE_AVATAR)
{
if(details.mAvatar.mSize == 0 || !pix.loadFromData(details.mAvatar.mData, details.mAvatar.mSize, "PNG"))
diff --git a/retroshare-gui/src/gui/gxs/GxsIdDetails.h b/retroshare-gui/src/gui/gxs/GxsIdDetails.h
index ef15c5fdd..7199f0565 100644
--- a/retroshare-gui/src/gui/gxs/GxsIdDetails.h
+++ b/retroshare-gui/src/gui/gxs/GxsIdDetails.h
@@ -50,11 +50,11 @@ class GxsIdDetails : public QObject
Q_OBJECT
public:
- static const int ICON_TYPE_AVATAR = 0x0001 ;
- static const int ICON_TYPE_PGP = 0x0002 ;
- static const int ICON_TYPE_RECOGN = 0x0004 ;
- static const int ICON_TYPE_ALL = 0x0007 ;
- static const int ICON_TYPE_REDACTED= 0x0008 ;
+ static const int ICON_TYPE_AVATAR = 0x0001 ;
+ static const int ICON_TYPE_PGP = 0x0002 ;
+ static const int ICON_TYPE_RECOGN = 0x0004 ;
+ static const int ICON_TYPE_REPUTATION = 0x0008 ;
+ static const int ICON_TYPE_ALL = 0x000f ;
GxsIdDetails();
virtual ~GxsIdDetails();
@@ -76,6 +76,7 @@ public:
static QString getNameForType(GxsIdDetailsType type, const RsIdentityDetails &details);
static QIcon getLoadingIcon(const RsGxsId &id);
+ static QIcon getReputationIcon(RsReputations::ReputationLevel icon_index);
static void GenerateCombinedPixmap(QPixmap &pixmap, const QList &icons, int iconSize);
diff --git a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp
index aa5edc91e..a2535c38e 100644
--- a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp
+++ b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp
@@ -35,12 +35,6 @@ GxsIdRSTreeWidgetItem::GxsIdRSTreeWidgetItem(const RSTreeWidgetItemCompareRole *
init();
}
-GxsIdRSTreeWidgetItem::GxsIdRSTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, uint32_t icon_mask,QTreeWidgetItem *parent)
- : QObject(NULL), RSTreeWidgetItem(compareRole, parent), mColumn(0), mIconTypeMask(icon_mask)
-{
- init();
-}
-
void GxsIdRSTreeWidgetItem::init()
{
mIdFound = false;
diff --git a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.h b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.h
index 472477841..dde64fdc6 100644
--- a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.h
+++ b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.h
@@ -40,8 +40,7 @@ class GxsIdRSTreeWidgetItem : public QObject, public RSTreeWidgetItem
Q_OBJECT
public:
- GxsIdRSTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, uint32_t icon_mask=GxsIdDetails::ICON_TYPE_ALL,QTreeWidget *parent = NULL);
- GxsIdRSTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, uint32_t icon_mask,QTreeWidgetItem *parent);
+ GxsIdRSTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, uint32_t icon_mask,QTreeWidget *parent = NULL);
void setId(const RsGxsId &id, int column, bool retryWhenFailed);
bool getId(RsGxsId &id);
diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp
index 8bf70fe48..fe36f9305 100644
--- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp
+++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp
@@ -1000,7 +1000,7 @@ QTreeWidgetItem *GxsForumThreadWidget::convertMsgToThreadWidget(const RsGxsForum
bool redacted = (reputation_level == RsReputations::REPUTATION_LOCALLY_NEGATIVE) ;
- GxsIdRSTreeWidgetItem *item = new GxsIdRSTreeWidgetItem(mThreadCompareRole,GxsIdDetails::ICON_TYPE_ALL || (redacted?(GxsIdDetails::ICON_TYPE_REDACTED):0));
+ GxsIdRSTreeWidgetItem *item = new GxsIdRSTreeWidgetItem(mThreadCompareRole,GxsIdDetails::ICON_TYPE_REPUTATION | GxsIdDetails::ICON_TYPE_AVATAR );
item->moveToThread(ui->threadTreeWidget->thread());
if(redacted)
@@ -1096,7 +1096,7 @@ QTreeWidgetItem *GxsForumThreadWidget::convertMsgToThreadWidget(const RsGxsForum
QTreeWidgetItem *GxsForumThreadWidget::generateMissingItem(const RsGxsMessageId &msgId)
{
- GxsIdRSTreeWidgetItem *item = new GxsIdRSTreeWidgetItem(mThreadCompareRole,GxsIdDetails::ICON_TYPE_ALL);
+ GxsIdRSTreeWidgetItem *item = new GxsIdRSTreeWidgetItem(mThreadCompareRole,GxsIdDetails::ICON_TYPE_REPUTATION | GxsIdDetails::ICON_TYPE_AVATAR);
item->setText(COLUMN_THREAD_TITLE, tr("[ ... Missing Message ... ]"));
item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID, QString::fromStdString(msgId.toStdString()));
From d4237450641f0588bb0b16de414e7219500d0fde Mon Sep 17 00:00:00 2001
From: csoler
Date: Sat, 24 Dec 2016 15:04:08 +0100
Subject: [PATCH 08/23] added column to show distribution data and moved
ReputationItemDelegate to GxsIdDetails
---
retroshare-gui/src/gui/Identity/IdDialog.cpp | 38 +-----------------
retroshare-gui/src/gui/gxs/GxsIdDetails.cpp | 40 +++++++++++++++++--
retroshare-gui/src/gui/gxs/GxsIdDetails.h | 26 +++++++++++-
.../gui/gxsforums/GxsForumThreadWidget.cpp | 22 +++++-----
.../src/gui/gxsforums/GxsForumThreadWidget.ui | 7 +++-
5 files changed, 80 insertions(+), 53 deletions(-)
diff --git a/retroshare-gui/src/gui/Identity/IdDialog.cpp b/retroshare-gui/src/gui/Identity/IdDialog.cpp
index 584c71d33..5dc948599 100644
--- a/retroshare-gui/src/gui/Identity/IdDialog.cpp
+++ b/retroshare-gui/src/gui/Identity/IdDialog.cpp
@@ -130,42 +130,6 @@ class TreeWidgetItem : public QTreeWidgetItem {
}
};
-// This class allows to draw the item in the share flags column using an appropriate size
-
-class ReputationItemDelegate: public QStyledItemDelegate
-{
-public:
- ReputationItemDelegate() {}
-
- virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
- {
- Q_ASSERT(index.isValid());
-
- QStyleOptionViewItemV4 opt = option;
- initStyleOption(&opt, index);
- // disable default icon
- opt.icon = QIcon();
- // draw default item
- QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter, 0);
-
- const QRect r = option.rect;
-
- // get pixmap
- unsigned int icon_index = qvariant_cast(index.data(Qt::DecorationRole));
-
- if(icon_index > 4)
- return ;
-
- QIcon icon = GxsIdDetails::getReputationIcon(RsReputations::ReputationLevel(icon_index));
-
- QPixmap pix = icon.pixmap(r.size());
-
- // draw pixmap at center of item
- const QPoint p = QPoint((r.width() - pix.width())/2, (r.height() - pix.height())/2);
- painter->drawPixmap(r.topLeft() + p, pix);
- }
-};
-
/** Constructor */
IdDialog::IdDialog(QWidget *parent) :
RsGxsUpdateBroadcastPage(rsIdentity, parent),
@@ -360,7 +324,7 @@ IdDialog::IdDialog(QWidget *parent) :
ui->idTreeWidget->setColumnWidth(RSID_COL_IDTYPE, 18 * fontWidth);
ui->idTreeWidget->setColumnWidth(RSID_COL_VOTES, 7 * fontWidth);
- ui->idTreeWidget->setItemDelegateForColumn(RSID_COL_VOTES,new ReputationItemDelegate()) ;
+ ui->idTreeWidget->setItemDelegateForColumn(RSID_COL_VOTES,new ReputationItemDelegate(RsReputations::ReputationLevel(0xff))) ;
//QHeaderView_setSectionResizeMode(ui->idTreeWidget->header(), QHeaderView::ResizeToContents);
diff --git a/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp b/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp
index a3f4b680b..0ccc4c2a2 100644
--- a/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp
+++ b/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp
@@ -53,6 +53,7 @@
#define REPUTATION_NEUTRAL_ICON ":/icons/bullet_grey_128.png"
#define REPUTATION_REMOTELY_NEGATIVE_ICON ":/icons/yellow_biohazard64.png"
#define REPUTATION_LOCALLY_NEGATIVE_ICON ":/icons/red_biohazard64.png"
+#define REPUTATION_VOID ":/icons/void_128.png"
#define TIMER_INTERVAL 500
#define MAX_ATTEMPTS 10
@@ -66,6 +67,35 @@ const int kRecognTagType_Dev_Translator = 3;
const int kRecognTagType_Dev_Patcher = 4;
const int kRecognTagType_Dev_Developer = 5;
+
+void ReputationItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ Q_ASSERT(index.isValid());
+
+ QStyleOptionViewItemV4 opt = option;
+ initStyleOption(&opt, index);
+ // disable default icon
+ opt.icon = QIcon();
+ // draw default item
+ QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter, 0);
+
+ const QRect r = option.rect;
+
+ // get pixmap
+ unsigned int icon_index = qvariant_cast(index.data(Qt::DecorationRole));
+
+ if(icon_index > mMaxLevelToDisplay)
+ return ;
+
+ QIcon icon = GxsIdDetails::getReputationIcon(RsReputations::ReputationLevel(icon_index),0xff);
+
+ QPixmap pix = icon.pixmap(r.size());
+
+ // draw pixmap at center of item
+ const QPoint p = QPoint((r.width() - pix.width())/2, (r.height() - pix.height())/2);
+ painter->drawPixmap(r.topLeft() + p, pix);
+}
+
/* The global object */
GxsIdDetails *GxsIdDetails::mInstance = NULL ;
@@ -964,8 +994,11 @@ QString nickname ;
return comment;
}
-QIcon GxsIdDetails::getReputationIcon(RsReputations::ReputationLevel icon_index)
+QIcon GxsIdDetails::getReputationIcon(RsReputations::ReputationLevel icon_index,uint32_t min_reputation)
{
+ if(icon_index >= min_reputation)
+ return QIcon(REPUTATION_VOID);
+
switch(icon_index)
{
case RsReputations::REPUTATION_LOCALLY_NEGATIVE: return QIcon(REPUTATION_LOCALLY_NEGATIVE_ICON) ; break ;
@@ -979,7 +1012,7 @@ QIcon GxsIdDetails::getReputationIcon(RsReputations::ReputationLevel icon_index)
}
}
-void GxsIdDetails::getIcons(const RsIdentityDetails &details, QList &icons,uint32_t icon_types)
+void GxsIdDetails::getIcons(const RsIdentityDetails &details, QList &icons,uint32_t icon_types,uint32_t minimal_required_reputation)
{
QPixmap pix ;
@@ -989,10 +1022,9 @@ void GxsIdDetails::getIcons(const RsIdentityDetails &details, QList &icon
icons.push_back(QIcon(IMAGE_BANNED)) ;
return ;
}
-
if(icon_types & ICON_TYPE_REPUTATION)
- icons.push_back(getReputationIcon(details.mReputation.mOverallReputationLevel)) ;
+ icons.push_back(getReputationIcon(details.mReputation.mOverallReputationLevel,minimal_required_reputation)) ;
if(icon_types & ICON_TYPE_AVATAR)
{
diff --git a/retroshare-gui/src/gui/gxs/GxsIdDetails.h b/retroshare-gui/src/gui/gxs/GxsIdDetails.h
index 7199f0565..39a6ad29d 100644
--- a/retroshare-gui/src/gui/gxs/GxsIdDetails.h
+++ b/retroshare-gui/src/gui/gxs/GxsIdDetails.h
@@ -29,6 +29,7 @@
#include
#include
#include
+#include
#include
@@ -45,6 +46,21 @@ enum GxsIdDetailsType
typedef void (*GxsIdDetailsCallbackFunction)(GxsIdDetailsType type, const RsIdentityDetails &details, QObject *object, const QVariant &data);
+// This class allows to draw the item in a reputation column using an appropriate size. The max_level_to_display parameter allows to replace
+// the icon by an empty icon when needed. This allows to keep the focus on the critical icons only.
+
+class ReputationItemDelegate: public QStyledItemDelegate
+{
+public:
+ ReputationItemDelegate(RsReputations::ReputationLevel max_level_to_display) : mMaxLevelToDisplay(max_level_to_display) {}
+
+ virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
+
+private:
+ uint32_t mMaxLevelToDisplay ;
+};
+
+
class GxsIdDetails : public QObject
{
Q_OBJECT
@@ -67,7 +83,13 @@ public:
static QString getName(const RsIdentityDetails &details);
static QString getComment(const RsIdentityDetails &details);
- static void getIcons(const RsIdentityDetails &details, QList &icons,uint32_t icon_types=ICON_TYPE_ALL);
+
+ /*!
+ * \brief getIcons
+ * Returns the list of icons to display along with the ID name. The types of icons to show is a compound of the ICON_TYPE_* flags.
+ * If reputation is needed and exceeds the minimal reputation, an empty/void icon is showsn . This allow to only show reputation for IDs for which a problem exists.
+ */
+ static void getIcons(const RsIdentityDetails &details, QList &icons, uint32_t icon_types=ICON_TYPE_ALL, uint32_t minimal_required_reputation=0xff);
static QString getEmptyIdText();
static QString getLoadingText(const RsGxsId &id);
@@ -76,7 +98,7 @@ public:
static QString getNameForType(GxsIdDetailsType type, const RsIdentityDetails &details);
static QIcon getLoadingIcon(const RsGxsId &id);
- static QIcon getReputationIcon(RsReputations::ReputationLevel icon_index);
+ static QIcon getReputationIcon(RsReputations::ReputationLevel icon_index, uint32_t min_reputation);
static void GenerateCombinedPixmap(QPixmap &pixmap, const QList &icons, int iconSize);
diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp
index fe36f9305..2171c1012 100644
--- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp
+++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp
@@ -67,13 +67,14 @@
#define VIEW_FLAT 2
/* Thread constants */
-#define COLUMN_THREAD_COUNT 6
-#define COLUMN_THREAD_TITLE 0
-#define COLUMN_THREAD_READ 1
-#define COLUMN_THREAD_DATE 2
-#define COLUMN_THREAD_AUTHOR 3
-#define COLUMN_THREAD_SIGNED 4
-#define COLUMN_THREAD_CONTENT 5
+#define COLUMN_THREAD_TITLE 0
+#define COLUMN_THREAD_READ 1
+#define COLUMN_THREAD_DATE 2
+#define COLUMN_THREAD_DISTRIBUTION 3
+#define COLUMN_THREAD_AUTHOR 4
+#define COLUMN_THREAD_SIGNED 5
+#define COLUMN_THREAD_CONTENT 6
+#define COLUMN_THREAD_COUNT 7
#define COLUMN_THREAD_DATA 0 // column for storing the userdata like msgid and parentid
@@ -137,6 +138,8 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget
mThreadCompareRole = new RSTreeWidgetItemCompareRole;
mThreadCompareRole->setRole(COLUMN_THREAD_DATE, ROLE_THREAD_SORT);
+ ui->threadTreeWidget->setItemDelegateForColumn(COLUMN_THREAD_DISTRIBUTION,new ReputationItemDelegate(RsReputations::REPUTATION_NEUTRAL)) ;
+
connect(ui->threadTreeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(threadListCustomPopupMenu(QPoint)));
connect(ui->postText, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuTextBrowser(QPoint)));
@@ -1000,7 +1003,7 @@ QTreeWidgetItem *GxsForumThreadWidget::convertMsgToThreadWidget(const RsGxsForum
bool redacted = (reputation_level == RsReputations::REPUTATION_LOCALLY_NEGATIVE) ;
- GxsIdRSTreeWidgetItem *item = new GxsIdRSTreeWidgetItem(mThreadCompareRole,GxsIdDetails::ICON_TYPE_REPUTATION | GxsIdDetails::ICON_TYPE_AVATAR );
+ GxsIdRSTreeWidgetItem *item = new GxsIdRSTreeWidgetItem(mThreadCompareRole,GxsIdDetails::ICON_TYPE_AVATAR );
item->moveToThread(ui->threadTreeWidget->thread());
if(redacted)
@@ -1008,6 +1011,7 @@ QTreeWidgetItem *GxsForumThreadWidget::convertMsgToThreadWidget(const RsGxsForum
else
item->setText(COLUMN_THREAD_TITLE, QString::fromUtf8(msg.mMeta.mMsgName.c_str()));
+ item->setData(COLUMN_THREAD_DISTRIBUTION,Qt::DecorationRole, reputation_level) ;
//msg.mMeta.mChildTs Was not updated when received new child
// so do it here.
@@ -1096,7 +1100,7 @@ QTreeWidgetItem *GxsForumThreadWidget::convertMsgToThreadWidget(const RsGxsForum
QTreeWidgetItem *GxsForumThreadWidget::generateMissingItem(const RsGxsMessageId &msgId)
{
- GxsIdRSTreeWidgetItem *item = new GxsIdRSTreeWidgetItem(mThreadCompareRole,GxsIdDetails::ICON_TYPE_REPUTATION | GxsIdDetails::ICON_TYPE_AVATAR);
+ GxsIdRSTreeWidgetItem *item = new GxsIdRSTreeWidgetItem(mThreadCompareRole,GxsIdDetails::ICON_TYPE_AVATAR);
item->setText(COLUMN_THREAD_TITLE, tr("[ ... Missing Message ... ]"));
item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID, QString::fromStdString(msgId.toStdString()));
diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.ui b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.ui
index a086d110c..ba0dd9640 100644
--- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.ui
+++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.ui
@@ -6,7 +6,7 @@
0
0
- 851
+ 1217
721
@@ -238,6 +238,11 @@
Date
+
+
+ Distribution
+
+
Author
From b34ab447da5f1dd3817e7639caefb82fa476d86a Mon Sep 17 00:00:00 2001
From: csoler
Date: Sat, 24 Dec 2016 17:29:53 +0100
Subject: [PATCH 09/23] added menu entries to vote for/against a forum poster
---
retroshare-gui/src/gui/Identity/IdDialog.ui | 2 +-
.../gui/gxsforums/GxsForumThreadWidget.cpp | 47 +++++++++++++++----
.../src/gui/gxsforums/GxsForumThreadWidget.h | 6 ++-
3 files changed, 44 insertions(+), 11 deletions(-)
diff --git a/retroshare-gui/src/gui/Identity/IdDialog.ui b/retroshare-gui/src/gui/Identity/IdDialog.ui
index 57fbc3649..a4e096b5f 100644
--- a/retroshare-gui/src/gui/Identity/IdDialog.ui
+++ b/retroshare-gui/src/gui/Identity/IdDialog.ui
@@ -485,7 +485,7 @@
-
- Auto-Ban all identities from this node
+ Auto-Ban all identities signed by the same node
diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp
index 2171c1012..33fa60e7c 100644
--- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp
+++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp
@@ -61,6 +61,9 @@
#define IMAGE_DOWNLOADALL ":/images/startall.png"
#define IMAGE_COPYLINK ":/images/copyrslink.png"
#define IMAGE_BIOHAZARD ":/icons/yellow_biohazard64.png"
+#define IMAGE_POSITIVE_OPINION ":/icons/png/thumbs-up.png"
+#define IMAGE_NEUTRAL_OPINION ":/icons/png/thumbs-neutral.png"
+#define IMAGE_NEGATIVE_OPINION ":/icons/png/thumbs-down.png"
#define VIEW_LAST_POST 0
#define VIEW_THREADED 1
@@ -100,7 +103,9 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget
mTokenTypeMessageData = nextTokenType();
mTokenTypeReplyMessage = nextTokenType();
mTokenTypeReplyForumMessage = nextTokenType();
- mTokenTypeBanAuthor = nextTokenType();
+ mTokenTypeNegativeAuthor = nextTokenType();
+ mTokenTypeNeutralAuthor = nextTokenType();
+ mTokenTypePositiveAuthor = nextTokenType();
setUpdateWhenInvisible(true);
@@ -421,9 +426,20 @@ void GxsForumThreadWidget::threadListCustomPopupMenu(QPoint /*point*/)
QAction *replyauthorAct = new QAction(QIcon(IMAGE_MESSAGEREPLY), tr("Reply with private message"), &contextMnu);
connect(replyauthorAct, SIGNAL(triggered()), this, SLOT(replytomessage()));
- QAction *flagasbadAct = new QAction(QIcon(IMAGE_BIOHAZARD), tr("Ban this author"), &contextMnu);
- flagasbadAct->setToolTip(tr("This will block/hide messages from this person, and notify neighbor nodes.")) ;
- connect(flagasbadAct, SIGNAL(triggered()), this, SLOT(flagpersonasbad()));
+ QAction *flagaspositiveAct = new QAction(QIcon(IMAGE_POSITIVE_OPINION), tr("Give positive opinion"), &contextMnu);
+ flagaspositiveAct->setToolTip(tr("This will block/hide messages from this person, and notify friend nodes.")) ;
+ flagaspositiveAct->setData(mTokenTypePositiveAuthor) ;
+ connect(flagaspositiveAct, SIGNAL(triggered()), this, SLOT(flagperson()));
+
+ QAction *flagasneutralAct = new QAction(QIcon(IMAGE_NEUTRAL_OPINION), tr("Give neutral opinion to this author"), &contextMnu);
+ flagasneutralAct->setToolTip(tr("Doing this, you trust your friends to decide to forward this message or not.")) ;
+ flagasneutralAct->setData(mTokenTypeNeutralAuthor) ;
+ connect(flagasneutralAct, SIGNAL(triggered()), this, SLOT(flagperson()));
+
+ QAction *flagasnegativeAct = new QAction(QIcon(IMAGE_NEGATIVE_OPINION), tr("Give negative opinion"), &contextMnu);
+ flagasnegativeAct->setToolTip(tr("This will block/hide messages from this person, and notify friend nodes.")) ;
+ flagasnegativeAct->setData(mTokenTypeNegativeAuthor) ;
+ connect(flagasnegativeAct, SIGNAL(triggered()), this, SLOT(flagperson()));
QAction *newthreadAct = new QAction(QIcon(IMAGE_MESSAGE), tr("Start New Thread"), &contextMnu);
newthreadAct->setEnabled (IS_GROUP_SUBSCRIBED(mSubscribeFlags));
@@ -504,7 +520,9 @@ void GxsForumThreadWidget::threadListCustomPopupMenu(QPoint /*point*/)
contextMnu.addAction(collapseAll);
contextMnu.addSeparator();
- contextMnu.addAction(flagasbadAct);
+ contextMnu.addAction(flagaspositiveAct);
+ contextMnu.addAction(flagasneutralAct);
+ contextMnu.addAction(flagasnegativeAct);
contextMnu.addSeparator();
contextMnu.addAction(replyauthorAct);
@@ -1013,6 +1031,17 @@ QTreeWidgetItem *GxsForumThreadWidget::convertMsgToThreadWidget(const RsGxsForum
item->setData(COLUMN_THREAD_DISTRIBUTION,Qt::DecorationRole, reputation_level) ;
+ QString rep_tooltip_str ;
+ switch(reputation_level)
+ {
+ case RsReputations::REPUTATION_LOCALLY_NEGATIVE: rep_tooltip_str = tr("You have banned this ID. The message will not be\ndisplayed nor forwarded to your friends.") ; break;
+ case RsReputations::REPUTATION_REMOTELY_NEGATIVE: rep_tooltip_str = tr("You have not set an opinion for this person,\n and your friends vote negatively: Spam regulation \nprevents the message to be forwarded to your friends.") ; break;
+ case RsReputations::REPUTATION_NEUTRAL: rep_tooltip_str = tr("You have not set an opinion for this person,\n and neither have your friends: Spam regulation\nprevents the message to be forwarded to your friends.") ; break;
+ default:
+ rep_tooltip_str = tr("Message will be forwarded to your friends.") ; break;
+ }
+ item->setData(COLUMN_THREAD_DISTRIBUTION,Qt::ToolTipRole,rep_tooltip_str) ;
+
//msg.mMeta.mChildTs Was not updated when received new child
// so do it here.
QDateTime qtime;
@@ -1832,7 +1861,7 @@ static QString buildReplyHeader(const RsMsgMetaData &meta)
return header;
}
-void GxsForumThreadWidget::flagpersonasbad()
+void GxsForumThreadWidget::flagperson()
{
// no need to use the token system for that, since we just need to find out the author's name, which is in the item.
@@ -1841,6 +1870,8 @@ void GxsForumThreadWidget::flagpersonasbad()
return;
}
+ uint32_t token_type = qobject_cast(sender())->data().toUInt();
+
// Get Message ... then complete replyMessageData().
RsGxsGrpMsgIdPair postId = std::make_pair(groupId(), mThreadId);
@@ -1857,7 +1888,7 @@ void GxsForumThreadWidget::flagpersonasbad()
vect.push_back(postId.second);
uint32_t token;
- mTokenQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, mTokenTypeBanAuthor);
+ mTokenQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, token_type);
}
void GxsForumThreadWidget::replytomessage()
@@ -2296,7 +2327,7 @@ void GxsForumThreadWidget::loadRequest(const TokenQueue *queue, const TokenReque
return;
}
- if (req.mUserType == mTokenTypeBanAuthor) {
+ if (req.mUserType == mTokenTypeNegativeAuthor) {
loadMsgData_BanAuthor(req.mToken);
return;
}
diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h
index 1cf109a81..2a3073f00 100644
--- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h
+++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h
@@ -108,7 +108,7 @@ private slots:
void downloadAllFiles();
void changedViewBox();
- void flagpersonasbad();
+ void flagperson();
void filterColumnChanged(int column);
void filterItems(const QString &text);
@@ -173,7 +173,9 @@ private:
uint32_t mTokenTypeMessageData;
uint32_t mTokenTypeReplyMessage;
uint32_t mTokenTypeReplyForumMessage;
- uint32_t mTokenTypeBanAuthor;
+ uint32_t mTokenTypeNegativeAuthor;
+ uint32_t mTokenTypePositiveAuthor;
+ uint32_t mTokenTypeNeutralAuthor;
/* Color definitions (for standard see qss.default) */
QColor mTextColorRead;
From c80d3ec1a498e360e0d85ee4b660246ef65e1af4 Mon Sep 17 00:00:00 2001
From: csoler
Date: Sun, 25 Dec 2016 23:12:07 +0100
Subject: [PATCH 10/23] added check for reputation before sending message ids
---
libretroshare/src/gxs/rsgxsnetservice.cc | 134 +++++++++++-------
.../src/serialiser/rsgxsupdateitems.h | 2 +-
2 files changed, 84 insertions(+), 52 deletions(-)
diff --git a/libretroshare/src/gxs/rsgxsnetservice.cc b/libretroshare/src/gxs/rsgxsnetservice.cc
index dd7ffebf7..a9c55eae0 100644
--- a/libretroshare/src/gxs/rsgxsnetservice.cc
+++ b/libretroshare/src/gxs/rsgxsnetservice.cc
@@ -1954,8 +1954,6 @@ void RsGxsNetService::updateServerSyncTS()
for(std::map::const_iterator mit = gxsMap.begin();mit != gxsMap.end(); ++mit)
{
- const RsGxsGroupId& grpId = mit->first;
-
// Check if the group is subscribed and restricted to a circle. If the circle has changed, update the
// global TS to reflect that change to clients who may be able to see/subscribe to that particular group.
@@ -2798,7 +2796,7 @@ void RsGxsNetService::locked_genReqMsgTransaction(NxsTransaction* tr)
#ifdef NXS_NET_DEBUG_1
GXSNETDEBUG_PG(item->PeerId(),grpId) << " msg ID = " << msgId ;
#endif
- if(reqListSize >= MAX_REQLIST_SIZE)
+ if(reqListSize >= (int)MAX_REQLIST_SIZE)
{
#ifdef NXS_NET_DEBUG_1
GXSNETDEBUG_PG(item->PeerId(),grpId) << ". reqlist too big. Pruning out this item for now." << std::endl;
@@ -2807,7 +2805,7 @@ void RsGxsNetService::locked_genReqMsgTransaction(NxsTransaction* tr)
continue ; // we should actually break, but we need to print some debug info.
}
- if(reqListSize < MAX_REQLIST_SIZE && msgIdSet.find(msgId) == msgIdSet.end())
+ if(reqListSize < (int)MAX_REQLIST_SIZE && msgIdSet.find(msgId) == msgIdSet.end())
{
bool noAuthor = syncItem->authorId.isNull();
@@ -2831,7 +2829,6 @@ void RsGxsNetService::locked_genReqMsgTransaction(NxsTransaction* tr)
// - if author is locally banned, do not download.
// - if author is not locally banned, download, whatever friends' opinion might be.
-#warning Update the code below to correctly send/recv dependign on reputation
if(rsIdentity && rsIdentity->overallReputationLevel(syncItem->authorId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
{
#ifdef NXS_NET_DEBUG_1
@@ -4213,57 +4210,92 @@ void RsGxsNetService::handleRecvSyncMessage(RsNxsSyncMsgReqItem *item,bool item_
if(canSendMsgIds(msgMetas, *grpMeta, peer, should_encrypt_to_this_circle_id))
{
+ RsReputations::ReputationLevel min_rep_for_anonymous ;
+ RsReputations::ReputationLevel min_rep_for_unknown_signed ;
+
+ min_rep_for_anonymous = (grpMeta->mSignFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG )?RsReputations::REPUTATION_REMOTELY_POSITIVE: RsReputations::REPUTATION_REMOTELY_NEGATIVE;
+ min_rep_for_unknown_signed = (grpMeta->mSignFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG_KNOWN)?RsReputations::REPUTATION_REMOTELY_POSITIVE: RsReputations::REPUTATION_REMOTELY_NEGATIVE;
+
for(std::vector::iterator vit = msgMetas.begin();vit != msgMetas.end(); ++vit)
- if(item->createdSinceTS < (*vit)->mPublishTs)
+ {
+ RsGxsMsgMetaData* m = *vit;
+
+ // if anti-spam is enabled, do not send messages from authors with bad reputation
+
+ RsIdentityDetails details ;
+
+ if(!rsIdentity->getIdDetails(m->mAuthorId,details))
{
- RsGxsMsgMetaData* m = *vit;
-
- RsNxsSyncMsgItem* mItem = new RsNxsSyncMsgItem(mServType);
- mItem->flag = RsNxsSyncGrpItem::FLAG_RESPONSE;
- mItem->grpId = m->mGroupId;
- mItem->msgId = m->mMsgId;
- mItem->authorId = m->mAuthorId;
- mItem->PeerId(peer);
- mItem->transactionNumber = transN;
-
- if(!should_encrypt_to_this_circle_id.isNull())
- {
-#ifdef NXS_NET_DEBUG_7
- GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " sending info item for msg id " << mItem->msgId << ". Transaction will be encrypted for group " << should_encrypt_to_this_circle_id << std::endl;
-#endif
- RsNxsItem *encrypted_item = NULL ;
- uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ;
-
- if(encryptSingleNxsItem(mItem, grpMeta->mCircleId,m->mGroupId, encrypted_item,status))
- {
- itemL.push_back(encrypted_item) ;
- delete mItem ;
- }
- else
- {
- // Something's not ready (probably the circle content. We could put on a vetting list, but actually the client will re-ask the list asap.
-
- std::cerr << " (EE) Cannot encrypt msg meta data. MsgId=" << mItem->msgId << ", grpId=" << mItem->grpId << ", circleId=" << should_encrypt_to_this_circle_id << ". Dropping the whole list." << std::endl;
-
- for(std::list::const_iterator it(itemL.begin());it!=itemL.end();++it)
- delete *it ;
-
- itemL.clear() ;
- break ;
- }
- }
- else
- {
-#ifdef NXS_NET_DEBUG_7
- GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " sending info item for msg id " << mItem->msgId << " in clear." << std::endl;
-#endif
- itemL.push_back(mItem);
- }
+ std::cerr << /* GXSNETDEBUG_PG(item->PeerId(),item->grpId) << */ " not sending grp message ID " << (*vit)->mMsgId << ", because the identity of the author is not accessible (unknown/not cached)" << std::endl;
+ continue ;
}
+ if(!(details.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED) && details.mReputation.mOverallReputationLevel < min_rep_for_anonymous)
+ {
+//#ifdef NXS_NET_DEBUG_0
+ std::cerr << /* GXSNETDEBUG_PG(item->PeerId(),item->grpId) << */ " not sending item ID " << (*vit)->mMsgId << ", because the author is anonymous has reputation level " << details.mReputation.mOverallReputationLevel << std::endl;
+//#endif
+ continue ;
+ }
+ if(!(details.mFlags & RS_IDENTITY_FLAGS_PGP_KNOWN) && details.mReputation.mOverallReputationLevel < min_rep_for_unknown_signed)
+ {
+//#ifdef NXS_NET_DEBUG_0
+ std::cerr << /* GXSNETDEBUG_PG(item->PeerId(),item->grpId) << */ " not sending item ID " << (*vit)->mMsgId << ", because the author is signed by unknown key, and has reputation level " << details.mReputation.mOverallReputationLevel << std::endl;
+//#endif
+ continue ;
+ }
+
+ // Check publish TS
+
+ if(item->createdSinceTS > (*vit)->mPublishTs)
+ {
#ifdef NXS_NET_DEBUG_0
- else
- GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " not sending item ID " << (*vit)->mMsgId << ", because it is too old (publishTS = " << (time(NULL)-(*vit)->mPublishTs)/86400 << " days ago" << std::endl;
+ GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " not sending item ID " << (*vit)->mMsgId << ", because it is too old (publishTS = " << (time(NULL)-(*vit)->mPublishTs)/86400 << " days ago" << std::endl;
#endif
+ continue ;
+ }
+
+ RsNxsSyncMsgItem* mItem = new RsNxsSyncMsgItem(mServType);
+ mItem->flag = RsNxsSyncGrpItem::FLAG_RESPONSE;
+ mItem->grpId = m->mGroupId;
+ mItem->msgId = m->mMsgId;
+ mItem->authorId = m->mAuthorId;
+ mItem->PeerId(peer);
+ mItem->transactionNumber = transN;
+
+ if(!should_encrypt_to_this_circle_id.isNull())
+ {
+#ifdef NXS_NET_DEBUG_7
+ GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " sending info item for msg id " << mItem->msgId << ". Transaction will be encrypted for group " << should_encrypt_to_this_circle_id << std::endl;
+#endif
+ RsNxsItem *encrypted_item = NULL ;
+ uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ;
+
+ if(encryptSingleNxsItem(mItem, grpMeta->mCircleId,m->mGroupId, encrypted_item,status))
+ {
+ itemL.push_back(encrypted_item) ;
+ delete mItem ;
+ }
+ else
+ {
+ // Something's not ready (probably the circle content. We could put on a vetting list, but actually the client will re-ask the list asap.
+
+ std::cerr << " (EE) Cannot encrypt msg meta data. MsgId=" << mItem->msgId << ", grpId=" << mItem->grpId << ", circleId=" << should_encrypt_to_this_circle_id << ". Dropping the whole list." << std::endl;
+
+ for(std::list::const_iterator it(itemL.begin());it!=itemL.end();++it)
+ delete *it ;
+
+ itemL.clear() ;
+ break ;
+ }
+ }
+ else
+ {
+#ifdef NXS_NET_DEBUG_7
+ GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " sending info item for msg id " << mItem->msgId << " in clear." << std::endl;
+#endif
+ itemL.push_back(mItem);
+ }
+ }
}
#ifdef NXS_NET_DEBUG_0
else
diff --git a/libretroshare/src/serialiser/rsgxsupdateitems.h b/libretroshare/src/serialiser/rsgxsupdateitems.h
index c32f6d3f4..117cc54d9 100644
--- a/libretroshare/src/serialiser/rsgxsupdateitems.h
+++ b/libretroshare/src/serialiser/rsgxsupdateitems.h
@@ -96,7 +96,7 @@ public:
virtual ~RsGxsGrpConfigItem() {}
virtual void clear() {}
- virtual std::ostream &print(std::ostream &out, uint16_t indent) { return out;}
+ virtual std::ostream &print(std::ostream &out, uint16_t /* indent */) { return out;}
virtual bool serialise(void *data,uint32_t& size) const ;
virtual uint32_t serial_size() const ;
From 811d084dfaca8f43c09749c0ff2cd2a5f4a51640 Mon Sep 17 00:00:00 2001
From: csoler
Date: Sun, 25 Dec 2016 23:43:29 +0100
Subject: [PATCH 11/23] only show distribution column if anti-spam is enabled
---
retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp
index 33fa60e7c..dff9e9607 100644
--- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp
+++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp
@@ -227,6 +227,7 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget
available posts from your subscribed friends, and make the \
forum visible to all other friends.
Afterwards you can unsubscribe from the context menu of the forum list at left.
"));
ui->threadTreeWidget->enableColumnCustomize(true);
+
}
GxsForumThreadWidget::~GxsForumThreadWidget()
@@ -815,8 +816,8 @@ static QString getDurationString(uint32_t days)
tw->ui->forumName->setText(QString::fromUtf8(group.mMeta.mGroupName.c_str()));
QString anti_spam_features1 ;
- if(IS_GROUP_PGP_KNOWN_AUTHED(tw->mSignFlags)) anti_spam_features1 = tr("Anonymous/unknown node IDs reputation threshold set to 0.4");
- else if(IS_GROUP_PGP_AUTHED(tw->mSignFlags)) anti_spam_features1 = tr("Anonymous IDs reputation threshold set to 0.4");
+ if(IS_GROUP_PGP_KNOWN_AUTHED(tw->mSignFlags)) anti_spam_features1 = tr("Anonymous/unknown posts forwarded if reputation is positive");
+ else if(IS_GROUP_PGP_AUTHED(tw->mSignFlags)) anti_spam_features1 = tr("Anonymous posts forwarded if reputation is positive");
tw->mForumDescription = QString("%1: \t%2
").arg(tr("Forum name"), QString::fromUtf8( group.mMeta.mGroupName.c_str()));
tw->mForumDescription += QString("%1: \t%2
").arg(tr("Subscribers")).arg(group.mMeta.mPop);
@@ -2105,6 +2106,8 @@ void GxsForumThreadWidget::loadGroupData(const uint32_t &token)
mStateHelper->setActive(mTokenTypeGroupData, true);
+ // Don't show the distribution column if the forum has no anti-spam
+ ui->threadTreeWidget->setColumnHidden(COLUMN_THREAD_DISTRIBUTION, !IS_GROUP_PGP_KNOWN_AUTHED(mForumGroup.mMeta.mSignFlags) && !(IS_GROUP_PGP_AUTHED(mForumGroup.mMeta.mSignFlags)));
ui->subscribeToolButton->setHidden(IS_GROUP_SUBSCRIBED(mSubscribeFlags)) ;
}
else
From 742a7648a4b7d0999670f4fbfaf07935c0f07417 Mon Sep 17 00:00:00 2001
From: csoler
Date: Mon, 26 Dec 2016 15:59:53 +0100
Subject: [PATCH 12/23] added display of warning for non forwarded posts
---
libretroshare/src/gxs/rsgenexchange.cc | 4 +
libretroshare/src/gxs/rsgenexchange.h | 1 +
libretroshare/src/gxs/rsgxsnetservice.cc | 29 ++----
libretroshare/src/gxs/rsnxs.h | 46 ++++++++++
libretroshare/src/retroshare/rsgxsforums.h | 35 ++++----
libretroshare/src/retroshare/rsgxsiface.h | 3 +
.../src/retroshare/rsgxsifacehelper.h | 5 ++
retroshare-gui/src/gui/Identity/IdDialog.cpp | 6 +-
.../gui/gxsforums/GxsForumThreadWidget.cpp | 83 +++++++++++++++---
retroshare-gui/src/gui/icons.qrc | 2 +
.../src/gui/icons/warning_red_128.png | Bin 0 -> 27339 bytes
.../src/gui/icons/warning_yellow_128.png | Bin 0 -> 25848 bytes
12 files changed, 160 insertions(+), 54 deletions(-)
create mode 100644 retroshare-gui/src/gui/icons/warning_red_128.png
create mode 100644 retroshare-gui/src/gui/icons/warning_yellow_128.png
diff --git a/libretroshare/src/gxs/rsgenexchange.cc b/libretroshare/src/gxs/rsgenexchange.cc
index 25d4e52d8..b002638da 100644
--- a/libretroshare/src/gxs/rsgenexchange.cc
+++ b/libretroshare/src/gxs/rsgenexchange.cc
@@ -1614,6 +1614,10 @@ uint32_t RsGenExchange::getDefaultSyncPeriod()
}
}
+RsReputations::ReputationLevel RsGenExchange::minReputationForForwardingMessages(uint32_t group_sign_flags,uint32_t identity_sign_flags)
+{
+ return RsNetworkExchangeService::minReputationForForwardingMessages(group_sign_flags,identity_sign_flags);
+}
uint32_t RsGenExchange::getSyncPeriod(const RsGxsGroupId& grpId)
{
RS_STACK_MUTEX(mGenMtx) ;
diff --git a/libretroshare/src/gxs/rsgenexchange.h b/libretroshare/src/gxs/rsgenexchange.h
index 0614ed2b1..95efbf2e1 100644
--- a/libretroshare/src/gxs/rsgenexchange.h
+++ b/libretroshare/src/gxs/rsgenexchange.h
@@ -658,6 +658,7 @@ public:
uint16_t serviceType() const { return mServType ; }
uint32_t serviceFullType() const { return ((uint32_t)mServType << 8) + (((uint32_t) RS_PKT_VERSION_SERVICE) << 24); }
+ virtual RsReputations::ReputationLevel minReputationForForwardingMessages(uint32_t group_sign_flags,uint32_t identity_flags);
protected:
/** Notifications **/
diff --git a/libretroshare/src/gxs/rsgxsnetservice.cc b/libretroshare/src/gxs/rsgxsnetservice.cc
index a9c55eae0..f8fa8ecc2 100644
--- a/libretroshare/src/gxs/rsgxsnetservice.cc
+++ b/libretroshare/src/gxs/rsgxsnetservice.cc
@@ -4210,18 +4210,10 @@ void RsGxsNetService::handleRecvSyncMessage(RsNxsSyncMsgReqItem *item,bool item_
if(canSendMsgIds(msgMetas, *grpMeta, peer, should_encrypt_to_this_circle_id))
{
- RsReputations::ReputationLevel min_rep_for_anonymous ;
- RsReputations::ReputationLevel min_rep_for_unknown_signed ;
-
- min_rep_for_anonymous = (grpMeta->mSignFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG )?RsReputations::REPUTATION_REMOTELY_POSITIVE: RsReputations::REPUTATION_REMOTELY_NEGATIVE;
- min_rep_for_unknown_signed = (grpMeta->mSignFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG_KNOWN)?RsReputations::REPUTATION_REMOTELY_POSITIVE: RsReputations::REPUTATION_REMOTELY_NEGATIVE;
-
for(std::vector::iterator vit = msgMetas.begin();vit != msgMetas.end(); ++vit)
{
RsGxsMsgMetaData* m = *vit;
- // if anti-spam is enabled, do not send messages from authors with bad reputation
-
RsIdentityDetails details ;
if(!rsIdentity->getIdDetails(m->mAuthorId,details))
@@ -4229,21 +4221,14 @@ void RsGxsNetService::handleRecvSyncMessage(RsNxsSyncMsgReqItem *item,bool item_
std::cerr << /* GXSNETDEBUG_PG(item->PeerId(),item->grpId) << */ " not sending grp message ID " << (*vit)->mMsgId << ", because the identity of the author is not accessible (unknown/not cached)" << std::endl;
continue ;
}
- if(!(details.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED) && details.mReputation.mOverallReputationLevel < min_rep_for_anonymous)
- {
-//#ifdef NXS_NET_DEBUG_0
- std::cerr << /* GXSNETDEBUG_PG(item->PeerId(),item->grpId) << */ " not sending item ID " << (*vit)->mMsgId << ", because the author is anonymous has reputation level " << details.mReputation.mOverallReputationLevel << std::endl;
-//#endif
- continue ;
- }
- if(!(details.mFlags & RS_IDENTITY_FLAGS_PGP_KNOWN) && details.mReputation.mOverallReputationLevel < min_rep_for_unknown_signed)
- {
-//#ifdef NXS_NET_DEBUG_0
- std::cerr << /* GXSNETDEBUG_PG(item->PeerId(),item->grpId) << */ " not sending item ID " << (*vit)->mMsgId << ", because the author is signed by unknown key, and has reputation level " << details.mReputation.mOverallReputationLevel << std::endl;
-//#endif
- continue ;
- }
+ if(details.mReputation.mOverallReputationLevel < minReputationForForwardingMessages(grpMeta->mSignFlags, details.mFlags))
+ {
+//#ifdef NXS_NET_DEBUG_0
+ std::cerr << /* GXSNETDEBUG_PG(item->PeerId(),item->grpId) << */ " not sending item ID " << (*vit)->mMsgId << ", because the author is flags " << std::hex << details.mFlags << std::dec << " and reputation level " << details.mReputation.mOverallReputationLevel << std::endl;
+//#endif
+ continue ;
+ }
// Check publish TS
if(item->createdSinceTS > (*vit)->mPublishTs)
diff --git a/libretroshare/src/gxs/rsnxs.h b/libretroshare/src/gxs/rsnxs.h
index 0613560b0..995377ed3 100644
--- a/libretroshare/src/gxs/rsnxs.h
+++ b/libretroshare/src/gxs/rsnxs.h
@@ -34,6 +34,8 @@
#include