mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-06-20 20:34:25 -04:00
commit
dafb2e6bc2
34 changed files with 1565 additions and 925 deletions
|
@ -187,6 +187,7 @@ void RsGenExchange::tick()
|
||||||
processGroupUpdatePublish();
|
processGroupUpdatePublish();
|
||||||
|
|
||||||
processGroupDelete();
|
processGroupDelete();
|
||||||
|
processMessageDelete();
|
||||||
|
|
||||||
processRecvdData();
|
processRecvdData();
|
||||||
|
|
||||||
|
@ -1620,6 +1621,11 @@ void RsGenExchange::deleteGroup(uint32_t& token, RsGxsGrpItem* grpItem)
|
||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
void RsGenExchange::deleteMsgs(uint32_t& token, const GxsMsgReq& msgs)
|
||||||
|
{
|
||||||
|
token = mDataAccess->generatePublicToken();
|
||||||
|
mMsgDeletePublish.push_back(MsgDeletePublish(msgs, token));
|
||||||
|
}
|
||||||
|
|
||||||
void RsGenExchange::publishMsg(uint32_t& token, RsGxsMsgItem *msgItem)
|
void RsGenExchange::publishMsg(uint32_t& token, RsGxsMsgItem *msgItem)
|
||||||
{
|
{
|
||||||
|
@ -2188,6 +2194,7 @@ void RsGenExchange::processRoutingClues()
|
||||||
|
|
||||||
mTrackingClues.clear() ;
|
mTrackingClues.clear() ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RsGenExchange::processGroupDelete()
|
void RsGenExchange::processGroupDelete()
|
||||||
{
|
{
|
||||||
RS_STACK_MUTEX(mGenMtx) ;
|
RS_STACK_MUTEX(mGenMtx) ;
|
||||||
|
@ -2234,6 +2241,52 @@ void RsGenExchange::processGroupDelete()
|
||||||
|
|
||||||
mGroupDeletePublish.clear();
|
mGroupDeletePublish.clear();
|
||||||
}
|
}
|
||||||
|
void RsGenExchange::processMessageDelete()
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mGenMtx) ;
|
||||||
|
#ifdef TODO
|
||||||
|
typedef std::pair<bool, RsGxsGroupId> GrpNote;
|
||||||
|
std::map<uint32_t, GrpNote> toNotify;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for( std::vector<MsgDeletePublish>::iterator vit = mMsgDeletePublish.begin(); vit != mMsgDeletePublish.end(); ++vit)
|
||||||
|
{
|
||||||
|
#ifdef TODO
|
||||||
|
uint32_t token = (*vit).mToken;
|
||||||
|
const RsGxsGroupId& groupId = gdp.grpItem->meta.mGroupId;
|
||||||
|
toNotify.insert(std::make_pair( token, GrpNote(true, groupId)));
|
||||||
|
#endif
|
||||||
|
mDataStore->removeMsgs( (*vit).mMsgs );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#warning TODO: notify for deleted messages
|
||||||
|
#ifdef SUSPENDED
|
||||||
|
std::list<RsGxsGroupId> grpDeleted;
|
||||||
|
std::map<uint32_t, GrpNote>::iterator mit = toNotify.begin();
|
||||||
|
for(; mit != toNotify.end(); ++mit)
|
||||||
|
{
|
||||||
|
GrpNote& note = mit->second;
|
||||||
|
uint8_t status = note.first ? RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE
|
||||||
|
: RsTokenService::GXS_REQUEST_V2_STATUS_FAILED;
|
||||||
|
|
||||||
|
mGrpNotify.insert(std::make_pair(mit->first, note.second));
|
||||||
|
mDataAccess->updatePublicRequestStatus(mit->first, status);
|
||||||
|
|
||||||
|
if(note.first)
|
||||||
|
grpDeleted.push_back(note.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!grpDeleted.empty())
|
||||||
|
{
|
||||||
|
RsGxsGroupChange* gc = new RsGxsGroupChange(RsGxsNotify::TYPE_PUBLISH, false);
|
||||||
|
gc->mGrpIdList = grpDeleted;
|
||||||
|
mNotifications.push_back(gc);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mMsgDeletePublish.clear();
|
||||||
|
}
|
||||||
|
|
||||||
bool RsGenExchange::checkKeys(const RsTlvSecurityKeySet& keySet)
|
bool RsGenExchange::checkKeys(const RsTlvSecurityKeySet& keySet)
|
||||||
{
|
{
|
||||||
|
@ -2957,7 +3010,7 @@ void RsGenExchange::performUpdateValidation()
|
||||||
|
|
||||||
if(gu.validUpdate)
|
if(gu.validUpdate)
|
||||||
{
|
{
|
||||||
if(gu.newGrp->metaData->mCircleType == GXS_CIRCLE_TYPE_YOUREYESONLY)
|
if(gu.newGrp->metaData->mCircleType == GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY)
|
||||||
gu.newGrp->metaData->mOriginator = gu.newGrp->PeerId();
|
gu.newGrp->metaData->mOriginator = gu.newGrp->PeerId();
|
||||||
|
|
||||||
// Keep subscriptionflag to what it was. This avoids clearing off the flag when updates to group meta information
|
// Keep subscriptionflag to what it was. This avoids clearing off the flag when updates to group meta information
|
||||||
|
|
|
@ -535,6 +535,14 @@ public:
|
||||||
*/
|
*/
|
||||||
void publishMsg(uint32_t& token, RsGxsMsgItem* msgItem);
|
void publishMsg(uint32_t& token, RsGxsMsgItem* msgItem);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Deletes the messages \n
|
||||||
|
* This will induce a related change message \n
|
||||||
|
* @param token
|
||||||
|
* @param msgs
|
||||||
|
*/
|
||||||
|
void deleteMsgs(uint32_t& token, const GxsMsgReq& msgs);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/*!
|
/*!
|
||||||
* This represents the group before its signature is calculated
|
* This represents the group before its signature is calculated
|
||||||
|
@ -657,6 +665,7 @@ private:
|
||||||
void processGroupUpdatePublish();
|
void processGroupUpdatePublish();
|
||||||
|
|
||||||
void processGroupDelete();
|
void processGroupDelete();
|
||||||
|
void processMessageDelete();
|
||||||
void processRoutingClues();
|
void processRoutingClues();
|
||||||
|
|
||||||
void publishMsgs();
|
void publishMsgs();
|
||||||
|
@ -869,6 +878,7 @@ private:
|
||||||
|
|
||||||
std::vector<GroupUpdatePublish> mGroupUpdatePublish;
|
std::vector<GroupUpdatePublish> mGroupUpdatePublish;
|
||||||
std::vector<GroupDeletePublish> mGroupDeletePublish;
|
std::vector<GroupDeletePublish> mGroupDeletePublish;
|
||||||
|
std::vector<MsgDeletePublish> mMsgDeletePublish;
|
||||||
|
|
||||||
std::map<RsGxsId,std::set<RsPeerId> > mRoutingClues ;
|
std::map<RsGxsId,std::set<RsPeerId> > mRoutingClues ;
|
||||||
std::list<std::pair<RsGxsMessageId,RsPeerId> > mTrackingClues ;
|
std::list<std::pair<RsGxsMessageId,RsPeerId> > mTrackingClues ;
|
||||||
|
|
|
@ -213,9 +213,11 @@ class RsGcxs
|
||||||
|
|
||||||
virtual int canSend(const RsGxsCircleId &circleId, const RsPgpId &id,bool& should_encrypt) = 0;
|
virtual int canSend(const RsGxsCircleId &circleId, const RsPgpId &id,bool& should_encrypt) = 0;
|
||||||
virtual int canReceive(const RsGxsCircleId &circleId, const RsPgpId &id) = 0;
|
virtual int canReceive(const RsGxsCircleId &circleId, const RsPgpId &id) = 0;
|
||||||
|
|
||||||
virtual bool recipients(const RsGxsCircleId &circleId, std::list<RsPgpId>& friendlist) = 0;
|
virtual bool recipients(const RsGxsCircleId &circleId, std::list<RsPgpId>& friendlist) = 0;
|
||||||
virtual bool recipients(const RsGxsCircleId &circleId, std::list<RsGxsId>& idlist) = 0;
|
virtual bool recipients(const RsGxsCircleId &circleId, const RsGxsGroupId& destination_group, std::list<RsGxsId>& idlist) = 0;
|
||||||
virtual bool isRecipient(const RsGxsCircleId &circleId, const RsGxsId& id) = 0;
|
|
||||||
|
virtual bool isRecipient(const RsGxsCircleId &circleId, const RsGxsGroupId& destination_group, const RsGxsId& id) = 0;
|
||||||
|
|
||||||
virtual bool getLocalCircleServerUpdateTS(const RsGxsCircleId& gid,time_t& grp_server_update_TS,time_t& msg_server_update_TS) =0;
|
virtual bool getLocalCircleServerUpdateTS(const RsGxsCircleId& gid,time_t& grp_server_update_TS,time_t& msg_server_update_TS) =0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -761,7 +761,7 @@ void RsGxsNetService::syncWithPeers()
|
||||||
RsNxsItem *encrypted_item = NULL ;
|
RsNxsItem *encrypted_item = NULL ;
|
||||||
uint32_t status ;
|
uint32_t status ;
|
||||||
|
|
||||||
if(encryptSingleNxsItem(msg, encrypt_to_this_circle_id, encrypted_item, status))
|
if(encryptSingleNxsItem(msg, encrypt_to_this_circle_id, grpId, encrypted_item, status))
|
||||||
sendItem(encrypted_item) ;
|
sendItem(encrypted_item) ;
|
||||||
else
|
else
|
||||||
std::cerr << "(WW) could not encrypt for circle ID " << encrypt_to_this_circle_id << ". Not yet in cache?" << std::endl;
|
std::cerr << "(WW) could not encrypt for circle ID " << encrypt_to_this_circle_id << ". Not yet in cache?" << std::endl;
|
||||||
|
@ -1270,7 +1270,7 @@ bool RsGxsNetService::locked_createTransactionFromPending(GrpCircleIdRequestVett
|
||||||
RsNxsItem *encrypted_item = NULL ;
|
RsNxsItem *encrypted_item = NULL ;
|
||||||
uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ;
|
uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ;
|
||||||
|
|
||||||
if(encryptSingleNxsItem(gItem, entry.mCircleId, encrypted_item,status))
|
if(encryptSingleNxsItem(gItem, entry.mCircleId, entry.mGroupId,encrypted_item,status))
|
||||||
{
|
{
|
||||||
itemL.push_back(encrypted_item) ;
|
itemL.push_back(encrypted_item) ;
|
||||||
delete gItem ;
|
delete gItem ;
|
||||||
|
@ -1321,7 +1321,7 @@ bool RsGxsNetService::locked_createTransactionFromPending(MsgCircleIdsRequestVet
|
||||||
RsNxsItem *encrypted_item = NULL ;
|
RsNxsItem *encrypted_item = NULL ;
|
||||||
uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ;
|
uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ;
|
||||||
|
|
||||||
if(encryptSingleNxsItem(mItem,msgPend->mCircleId,encrypted_item,status))
|
if(encryptSingleNxsItem(mItem,msgPend->mCircleId,msgPend->mGrpId,encrypted_item,status))
|
||||||
{
|
{
|
||||||
itemL.push_back(encrypted_item) ;
|
itemL.push_back(encrypted_item) ;
|
||||||
delete mItem ;
|
delete mItem ;
|
||||||
|
@ -3665,7 +3665,7 @@ bool RsGxsNetService::locked_addTransaction(NxsTransaction* tr)
|
||||||
// Returns false when the keys are not loaded. Question to solve: what do we do if we miss some keys??
|
// Returns false when the keys are not loaded. Question to solve: what do we do if we miss some keys??
|
||||||
// We should probably send anyway.
|
// We should probably send anyway.
|
||||||
|
|
||||||
bool RsGxsNetService::encryptSingleNxsItem(RsNxsItem *item, const RsGxsCircleId& destination_circle, RsNxsItem *&encrypted_item, uint32_t& status)
|
bool RsGxsNetService::encryptSingleNxsItem(RsNxsItem *item, const RsGxsCircleId& destination_circle, const RsGxsGroupId& destination_group, RsNxsItem *&encrypted_item, uint32_t& status)
|
||||||
{
|
{
|
||||||
encrypted_item = NULL ;
|
encrypted_item = NULL ;
|
||||||
status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ;
|
status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ;
|
||||||
|
@ -3678,7 +3678,7 @@ bool RsGxsNetService::encryptSingleNxsItem(RsNxsItem *item, const RsGxsCircleId&
|
||||||
|
|
||||||
std::list<RsGxsId> recipients ;
|
std::list<RsGxsId> recipients ;
|
||||||
|
|
||||||
if(!mCircles->recipients(destination_circle,recipients))
|
if(!mCircles->recipients(destination_circle,destination_group,recipients))
|
||||||
{
|
{
|
||||||
std::cerr << " (EE) Cannot encrypt transaction: recipients list not available. Should re-try later." << std::endl;
|
std::cerr << " (EE) Cannot encrypt transaction: recipients list not available. Should re-try later." << std::endl;
|
||||||
status = RS_NXS_ITEM_ENCRYPTION_STATUS_CIRCLE_ERROR ;
|
status = RS_NXS_ITEM_ENCRYPTION_STATUS_CIRCLE_ERROR ;
|
||||||
|
@ -4048,7 +4048,7 @@ void RsGxsNetService::handleRecvSyncGroup(RsNxsSyncGrpReqItem *item)
|
||||||
RsNxsItem *encrypted_item = NULL ;
|
RsNxsItem *encrypted_item = NULL ;
|
||||||
uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ;
|
uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ;
|
||||||
|
|
||||||
if(encryptSingleNxsItem(gItem, grpMeta->mCircleId, encrypted_item,status))
|
if(encryptSingleNxsItem(gItem, grpMeta->mCircleId,mit->first, encrypted_item,status))
|
||||||
{
|
{
|
||||||
itemL.push_back(encrypted_item) ;
|
itemL.push_back(encrypted_item) ;
|
||||||
delete gItem ;
|
delete gItem ;
|
||||||
|
@ -4158,7 +4158,7 @@ bool RsGxsNetService::canSendGrpId(const RsPeerId& sslId, RsGxsGrpMetaData& grpM
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if(circleType == GXS_CIRCLE_TYPE_YOUREYESONLY)
|
if(circleType == GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY)
|
||||||
{
|
{
|
||||||
#ifdef NXS_NET_DEBUG_4
|
#ifdef NXS_NET_DEBUG_4
|
||||||
GXSNETDEBUG_PG(sslId,grpMeta.mGroupId)<< " YOUREYESONLY, checking further"<< std::endl;
|
GXSNETDEBUG_PG(sslId,grpMeta.mGroupId)<< " YOUREYESONLY, checking further"<< std::endl;
|
||||||
|
@ -4286,7 +4286,7 @@ bool RsGxsNetService::checkCanRecvMsgFromPeer(const RsPeerId& sslId, const RsGxs
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if(circleType == GXS_CIRCLE_TYPE_YOUREYESONLY) // do not attempt to sync msg unless to originator or those permitted
|
if(circleType == GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY) // do not attempt to sync msg unless to originator or those permitted
|
||||||
{
|
{
|
||||||
#ifdef NXS_NET_DEBUG_4
|
#ifdef NXS_NET_DEBUG_4
|
||||||
GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " YOUREYESONLY, checking further" << std::endl;
|
GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " YOUREYESONLY, checking further" << std::endl;
|
||||||
|
@ -4471,7 +4471,7 @@ void RsGxsNetService::handleRecvSyncMessage(RsNxsSyncMsgReqItem *item,bool item_
|
||||||
RsNxsItem *encrypted_item = NULL ;
|
RsNxsItem *encrypted_item = NULL ;
|
||||||
uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ;
|
uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ;
|
||||||
|
|
||||||
if(encryptSingleNxsItem(mItem, grpMeta->mCircleId, encrypted_item,status))
|
if(encryptSingleNxsItem(mItem, grpMeta->mCircleId,m->mGroupId, encrypted_item,status))
|
||||||
{
|
{
|
||||||
itemL.push_back(encrypted_item) ;
|
itemL.push_back(encrypted_item) ;
|
||||||
delete mItem ;
|
delete mItem ;
|
||||||
|
@ -4619,7 +4619,7 @@ bool RsGxsNetService::canSendMsgIds(std::vector<RsGxsMsgMetaData*>& msgMetas, co
|
||||||
++i ;
|
++i ;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(mCircles->isLoaded(circleId) && mCircles->isRecipient(circleId, msgMetas[i]->mAuthorId))
|
if(mCircles->isLoaded(circleId) && mCircles->isRecipient(circleId, grpMeta.mGroupId, msgMetas[i]->mAuthorId))
|
||||||
{
|
{
|
||||||
++i ;
|
++i ;
|
||||||
continue ;
|
continue ;
|
||||||
|
@ -4645,7 +4645,7 @@ bool RsGxsNetService::canSendMsgIds(std::vector<RsGxsMsgMetaData*>& msgMetas, co
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(circleType == GXS_CIRCLE_TYPE_YOUREYESONLY)
|
if(circleType == GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY)
|
||||||
{
|
{
|
||||||
#ifdef NXS_NET_DEBUG_4
|
#ifdef NXS_NET_DEBUG_4
|
||||||
GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: YOUR EYES ONLY" << std::endl;
|
GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: YOUR EYES ONLY" << std::endl;
|
||||||
|
|
|
@ -454,7 +454,7 @@ private:
|
||||||
/*!
|
/*!
|
||||||
* encrypts/decrypts the transaction for the destination circle id.
|
* encrypts/decrypts the transaction for the destination circle id.
|
||||||
*/
|
*/
|
||||||
bool encryptSingleNxsItem(RsNxsItem *item, const RsGxsCircleId& destination_circle, RsNxsItem *& encrypted_item, uint32_t &status) ;
|
bool encryptSingleNxsItem(RsNxsItem *item, const RsGxsCircleId& destination_circle, const RsGxsGroupId &destination_group, RsNxsItem *& encrypted_item, uint32_t &status) ;
|
||||||
bool decryptSingleNxsItem(const RsNxsEncryptedDataItem *encrypted_item, RsNxsItem *&nxsitem, std::vector<RsTlvSecurityKey> *private_keys=NULL);
|
bool decryptSingleNxsItem(const RsNxsEncryptedDataItem *encrypted_item, RsNxsItem *&nxsitem, std::vector<RsTlvSecurityKey> *private_keys=NULL);
|
||||||
bool processTransactionForDecryption(NxsTransaction *tr); // return false when the keys are not loaded => need retry later
|
bool processTransactionForDecryption(NxsTransaction *tr); // return false when the keys are not loaded => need retry later
|
||||||
|
|
||||||
|
|
|
@ -291,7 +291,7 @@ bool MsgCircleIdsRequestVetting::cleared()
|
||||||
}
|
}
|
||||||
|
|
||||||
for(uint32_t i=0;i<mMsgs.size();)
|
for(uint32_t i=0;i<mMsgs.size();)
|
||||||
if(!mCircles->isRecipient(mCircleId,mMsgs[i].mAuthorId))
|
if(!mCircles->isRecipient(mCircleId,mGrpId,mMsgs[i].mAuthorId))
|
||||||
{
|
{
|
||||||
std::cerr << "(WW) MsgCircleIdsRequestVetting::cleared() filtering out message " << mMsgs[i].mMsgId << " because it's signed by author " << mMsgs[i].mAuthorId << " which is not in circle " << mCircleId << std::endl;
|
std::cerr << "(WW) MsgCircleIdsRequestVetting::cleared() filtering out message " << mMsgs[i].mMsgId << " because it's signed by author " << mMsgs[i].mAuthorId << " which is not in circle " << mCircleId << std::endl;
|
||||||
|
|
||||||
|
|
|
@ -162,4 +162,15 @@ public:
|
||||||
uint32_t mToken;
|
uint32_t mToken;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class MsgDeletePublish
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MsgDeletePublish(const GxsMsgReq& msgs, uint32_t token)
|
||||||
|
: mMsgs(msgs), mToken(token) {}
|
||||||
|
|
||||||
|
GxsMsgReq mMsgs ;
|
||||||
|
uint32_t mToken;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* GXSUTIL_H_ */
|
#endif /* GXSUTIL_H_ */
|
||||||
|
|
|
@ -121,13 +121,13 @@ std::string PGPKeyParser::extractRadixPartFromArmouredKey(const std::string& pgp
|
||||||
std::string PGPKeyManagement::makeArmouredKey(const unsigned char *keydata,size_t key_size,const std::string& version_string)
|
std::string PGPKeyManagement::makeArmouredKey(const unsigned char *keydata,size_t key_size,const std::string& version_string)
|
||||||
{
|
{
|
||||||
std::string outstring ;
|
std::string outstring ;
|
||||||
Radix64::encode((const char *)keydata,key_size,outstring) ;
|
Radix64::encode(keydata,key_size,outstring) ;
|
||||||
|
|
||||||
uint32_t crc = compute24bitsCRC((unsigned char *)keydata,key_size) ;
|
uint32_t crc = compute24bitsCRC((unsigned char *)keydata,key_size) ;
|
||||||
|
|
||||||
unsigned char tmp[3] = { uint8_t((crc >> 16) & 0xff), uint8_t((crc >> 8) & 0xff), uint8_t(crc & 0xff) } ;
|
unsigned char tmp[3] = { uint8_t((crc >> 16) & 0xff), uint8_t((crc >> 8) & 0xff), uint8_t(crc & 0xff) } ;
|
||||||
std::string crc_string ;
|
std::string crc_string ;
|
||||||
Radix64::encode((const char *)tmp,3,crc_string) ;
|
Radix64::encode(tmp,3,crc_string) ;
|
||||||
|
|
||||||
#ifdef DEBUG_PGPUTIL
|
#ifdef DEBUG_PGPUTIL
|
||||||
std::cerr << "After signature pruning: " << std::endl;
|
std::cerr << "After signature pruning: " << std::endl;
|
||||||
|
|
|
@ -109,7 +109,7 @@ std::string RsCertificate::toStdString() const
|
||||||
|
|
||||||
std::string out_string ;
|
std::string out_string ;
|
||||||
|
|
||||||
Radix64::encode((char *)buf, p, out_string) ;
|
Radix64::encode(buf, p, out_string) ;
|
||||||
|
|
||||||
// Now slice up to 64 chars.
|
// Now slice up to 64 chars.
|
||||||
//
|
//
|
||||||
|
|
|
@ -48,18 +48,25 @@ class RsGxsCircles;
|
||||||
extern RsGxsCircles *rsGxsCircles;
|
extern RsGxsCircles *rsGxsCircles;
|
||||||
|
|
||||||
typedef RsPgpId RsPgpId;
|
typedef RsPgpId RsPgpId;
|
||||||
//typedef RsGxsCircleId RsCircleInternalId;
|
|
||||||
|
|
||||||
#define GXS_CIRCLE_TYPE_PUBLIC 0x0001
|
// The meaning of the different circle types is:
|
||||||
#define GXS_CIRCLE_TYPE_EXTERNAL 0x0002
|
//
|
||||||
#define GXS_CIRCLE_TYPE_YOUREYESONLY 0x0003
|
//
|
||||||
#define GXS_CIRCLE_TYPE_LOCAL 0x0004
|
static const uint32_t GXS_CIRCLE_TYPE_PUBLIC = 0x0001 ; // not restricted to a circle
|
||||||
|
static const uint32_t GXS_CIRCLE_TYPE_EXTERNAL = 0x0002 ; // restricted to an external circle, made of RsGxsId
|
||||||
|
static const uint32_t GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY = 0x0003 ; // restricted to a subset of friend nodes of a given RS node given by a RsPgpId list
|
||||||
|
static const uint32_t GXS_CIRCLE_TYPE_LOCAL = 0x0004 ; // not distributed at all
|
||||||
|
static const uint32_t GXS_CIRCLE_TYPE_EXT_SELF = 0x0005 ; // self-restricted. Not used, except at creation time when the circle ID isn't known yet. Set to EXTERNAL afterwards.
|
||||||
|
static const uint32_t GXS_CIRCLE_TYPE_YOUR_EYES_ONLY = 0x0006 ; // distributed to nodes signed by your own PGP key only.
|
||||||
|
|
||||||
// A special one - used only by Circles themselves - meaning Circle ID == Group ID.
|
static const uint32_t GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST = 0x0001 ;// user is validated by circle admin
|
||||||
#define GXS_CIRCLE_TYPE_EXT_SELF 0x0005
|
static const uint32_t GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED = 0x0002 ;// user has subscribed the group
|
||||||
|
static const uint32_t GXS_EXTERNAL_CIRCLE_FLAGS_KEY_AVAILABLE = 0x0004 ;// key is available, so we can encrypt for this circle
|
||||||
|
static const uint32_t GXS_EXTERNAL_CIRCLE_FLAGS_ALLOWED = 0x0007 ;// user is allowed. Combines all flags above.
|
||||||
|
|
||||||
/* Permissions is part of GroupMetaData
|
static const uint32_t GXS_CIRCLE_FLAGS_IS_EXTERNAL = 0x0008 ;// user is allowed
|
||||||
*/
|
|
||||||
|
/* Permissions is part of GroupMetaData */
|
||||||
|
|
||||||
class GxsPermissions
|
class GxsPermissions
|
||||||
{
|
{
|
||||||
|
@ -72,7 +79,6 @@ public:
|
||||||
RsGxsCircleId mInternalCircle; // if Originator == ownId, otherwise blank.
|
RsGxsCircleId mInternalCircle; // if Originator == ownId, otherwise blank.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class RsGxsCircleGroup
|
class RsGxsCircleGroup
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -100,37 +106,19 @@ class RsGxsCircleMsg
|
||||||
class RsGxsCircleDetails
|
class RsGxsCircleDetails
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RsGxsCircleDetails() : mCircleType(GXS_CIRCLE_TYPE_EXTERNAL), mIsExternal(true), mAmIAllowed(false) {}
|
RsGxsCircleDetails() : mCircleType(GXS_CIRCLE_TYPE_EXTERNAL), mAmIAllowed(false) {}
|
||||||
|
|
||||||
RsGxsCircleId mCircleId;
|
RsGxsCircleId mCircleId;
|
||||||
std::string mCircleName;
|
std::string mCircleName;
|
||||||
|
|
||||||
uint32_t mCircleType;
|
uint32_t mCircleType;
|
||||||
bool mIsExternal;
|
|
||||||
bool mAmIAllowed ;
|
|
||||||
|
|
||||||
bool operator ==(const RsGxsCircleDetails& rGxsDetails) {
|
bool mAmIAllowed ; // true when one of load GXS ids belong to the circle allowed list (admin list & subscribed list).
|
||||||
return ( mCircleId == rGxsDetails.mCircleId
|
|
||||||
&& mCircleName == rGxsDetails.mCircleName
|
|
||||||
&& mCircleType == rGxsDetails.mCircleType
|
|
||||||
&& mIsExternal == rGxsDetails.mIsExternal
|
|
||||||
&& mAllowedAnonPeers == rGxsDetails.mAllowedAnonPeers
|
|
||||||
&& mAllowedSignedPeers == rGxsDetails.mAllowedSignedPeers
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator !=(const RsGxsCircleDetails& rGxsDetails) {
|
std::set<RsGxsId> mAllowedGxsIds; // This crosses admin list and subscribed list
|
||||||
return ( mCircleId != rGxsDetails.mCircleId
|
std::set<RsPgpId> mAllowedNodes;
|
||||||
|| mCircleName != rGxsDetails.mCircleName
|
|
||||||
|| mCircleType != rGxsDetails.mCircleType
|
|
||||||
|| mIsExternal != rGxsDetails.mIsExternal
|
|
||||||
|| mAllowedAnonPeers != rGxsDetails.mAllowedAnonPeers
|
|
||||||
|| mAllowedSignedPeers != rGxsDetails.mAllowedSignedPeers
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::set<RsGxsId> mAllowedAnonPeers;
|
std::map<RsGxsId,uint32_t> mSubscriptionFlags ; // subscription flags for all ids
|
||||||
std::map<RsPgpId, std::set<RsGxsId> > mAllowedSignedPeers;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class RsGxsCircles: public RsGxsIfaceHelper
|
class RsGxsCircles: public RsGxsIfaceHelper
|
||||||
|
@ -147,6 +135,11 @@ virtual bool getCircleDetails(const RsGxsCircleId &id, RsGxsCircleDetails &detai
|
||||||
virtual bool getCircleExternalIdList(std::list<RsGxsCircleId> &circleIds) = 0;
|
virtual bool getCircleExternalIdList(std::list<RsGxsCircleId> &circleIds) = 0;
|
||||||
virtual bool getCirclePersonalIdList(std::list<RsGxsCircleId> &circleIds) = 0;
|
virtual bool getCirclePersonalIdList(std::list<RsGxsCircleId> &circleIds) = 0;
|
||||||
|
|
||||||
|
/* membership management for external circles */
|
||||||
|
|
||||||
|
virtual bool requestCircleMembership(const RsGxsId& own_gxsid,const RsGxsCircleId& circle_id)=0 ;
|
||||||
|
virtual bool cancelCircleMembership(const RsGxsId& own_gxsid,const RsGxsCircleId& circle_id)=0 ;
|
||||||
|
|
||||||
/* standard load */
|
/* standard load */
|
||||||
virtual bool getGroupData(const uint32_t &token, std::vector<RsGxsCircleGroup> &groups) = 0;
|
virtual bool getGroupData(const uint32_t &token, std::vector<RsGxsCircleGroup> &groups) = 0;
|
||||||
|
|
||||||
|
|
|
@ -235,6 +235,7 @@ virtual bool getIdDetails(const RsGxsId &id, RsIdentityDetails &details) = 0;
|
||||||
|
|
||||||
// Fills up list of all own ids. Returns false if ids are not yet loaded.
|
// Fills up list of all own ids. Returns false if ids are not yet loaded.
|
||||||
virtual bool getOwnIds(std::list<RsGxsId> &ownIds) = 0;
|
virtual bool getOwnIds(std::list<RsGxsId> &ownIds) = 0;
|
||||||
|
virtual bool isOwnId(const RsGxsId& id) = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
virtual bool submitOpinion(uint32_t& token, const RsGxsId &id,
|
virtual bool submitOpinion(uint32_t& token, const RsGxsId &id,
|
||||||
|
|
|
@ -1083,12 +1083,12 @@ bool p3Peers::GetPGPBase64StringAndCheckSum( const RsPgpId& gpg_id,
|
||||||
if(!AuthGPG::getAuthGPG()->exportPublicKey(gpg_id,mem_block,mem_block_size,false,false))
|
if(!AuthGPG::getAuthGPG()->exportPublicKey(gpg_id,mem_block,mem_block_size,false,false))
|
||||||
return false ;
|
return false ;
|
||||||
|
|
||||||
Radix64::encode((const char *)mem_block,mem_block_size,gpg_base64_string) ;
|
Radix64::encode(mem_block,mem_block_size,gpg_base64_string) ;
|
||||||
|
|
||||||
uint32_t crc = PGPKeyManagement::compute24bitsCRC((unsigned char *)mem_block,mem_block_size) ;
|
uint32_t crc = PGPKeyManagement::compute24bitsCRC((unsigned char *)mem_block,mem_block_size) ;
|
||||||
|
|
||||||
unsigned char tmp[3] = { uint8_t((crc >> 16) & 0xff), uint8_t((crc >> 8) & 0xff), uint8_t(crc & 0xff) } ;
|
unsigned char tmp[3] = { uint8_t((crc >> 16) & 0xff), uint8_t((crc >> 8) & 0xff), uint8_t(crc & 0xff) } ;
|
||||||
Radix64::encode((const char *)tmp,3,gpg_base64_checksum) ;
|
Radix64::encode(tmp,3,gpg_base64_checksum) ;
|
||||||
|
|
||||||
delete[] mem_block ;
|
delete[] mem_block ;
|
||||||
|
|
||||||
|
|
|
@ -1345,15 +1345,13 @@ int RsServer::StartupRetroShare()
|
||||||
mGxsCircles, mGxsCircles->getServiceInfo(),
|
mGxsCircles, mGxsCircles->getServiceInfo(),
|
||||||
mGxsIdService, mGxsCircles,mGxsIdService,
|
mGxsIdService, mGxsCircles,mGxsIdService,
|
||||||
pgpAuxUtils,
|
pgpAuxUtils,
|
||||||
true,false); // synchronise group automatic
|
true, // synchronise group automatic
|
||||||
// don't sync messages at all.
|
true); // sync messages automatic, since they contain subscription requests.
|
||||||
|
|
||||||
mGxsCircles->setNetworkExchangeService(gxscircles_ns) ;
|
mGxsCircles->setNetworkExchangeService(gxscircles_ns) ;
|
||||||
|
|
||||||
/**** Posted GXS service ****/
|
/**** Posted GXS service ****/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
RsGeneralDataService* posted_ds = new RsDataService(currGxsDir + "/", "posted_db",
|
RsGeneralDataService* posted_ds = new RsDataService(currGxsDir + "/", "posted_db",
|
||||||
RS_SERVICE_GXS_TYPE_POSTED,
|
RS_SERVICE_GXS_TYPE_POSTED,
|
||||||
NULL, rsInitConfig->gxs_passwd);
|
NULL, rsInitConfig->gxs_passwd);
|
||||||
|
|
|
@ -35,6 +35,7 @@ uint32_t RsGxsCircleSerialiser::size(RsItem *item)
|
||||||
{
|
{
|
||||||
RsGxsCircleGroupItem* grp_item = NULL;
|
RsGxsCircleGroupItem* grp_item = NULL;
|
||||||
RsGxsCircleMsgItem* snap_item = NULL;
|
RsGxsCircleMsgItem* snap_item = NULL;
|
||||||
|
RsGxsCircleSubscriptionRequestItem* subr_item = NULL;
|
||||||
|
|
||||||
if((grp_item = dynamic_cast<RsGxsCircleGroupItem*>(item)) != NULL)
|
if((grp_item = dynamic_cast<RsGxsCircleGroupItem*>(item)) != NULL)
|
||||||
{
|
{
|
||||||
|
@ -43,6 +44,10 @@ uint32_t RsGxsCircleSerialiser::size(RsItem *item)
|
||||||
else if((snap_item = dynamic_cast<RsGxsCircleMsgItem*>(item)) != NULL)
|
else if((snap_item = dynamic_cast<RsGxsCircleMsgItem*>(item)) != NULL)
|
||||||
{
|
{
|
||||||
return sizeGxsCircleMsgItem(snap_item);
|
return sizeGxsCircleMsgItem(snap_item);
|
||||||
|
}
|
||||||
|
else if((subr_item = dynamic_cast<RsGxsCircleSubscriptionRequestItem*>(item)) != NULL)
|
||||||
|
{
|
||||||
|
return sizeGxsCircleSubscriptionRequestItem(subr_item);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return 0 ;
|
return 0 ;
|
||||||
|
@ -52,6 +57,7 @@ bool RsGxsCircleSerialiser::serialise(RsItem *item, void *data, uint32_t *size)
|
||||||
{
|
{
|
||||||
RsGxsCircleGroupItem* grp_item = NULL;
|
RsGxsCircleGroupItem* grp_item = NULL;
|
||||||
RsGxsCircleMsgItem* snap_item = NULL;
|
RsGxsCircleMsgItem* snap_item = NULL;
|
||||||
|
RsGxsCircleSubscriptionRequestItem* subr_item = NULL;
|
||||||
|
|
||||||
if((grp_item = dynamic_cast<RsGxsCircleGroupItem*>(item)) != NULL)
|
if((grp_item = dynamic_cast<RsGxsCircleGroupItem*>(item)) != NULL)
|
||||||
{
|
{
|
||||||
|
@ -61,6 +67,10 @@ bool RsGxsCircleSerialiser::serialise(RsItem *item, void *data, uint32_t *size)
|
||||||
{
|
{
|
||||||
return serialiseGxsCircleMsgItem(snap_item, data, size);
|
return serialiseGxsCircleMsgItem(snap_item, data, size);
|
||||||
}
|
}
|
||||||
|
else if((subr_item = dynamic_cast<RsGxsCircleSubscriptionRequestItem*>(item)) != NULL)
|
||||||
|
{
|
||||||
|
return serialiseGxsCircleSubscriptionRequestItem(subr_item, data, size);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,8 +83,7 @@ RsItem* RsGxsCircleSerialiser::deserialise(void* data, uint32_t* size)
|
||||||
/* get the type and size */
|
/* get the type and size */
|
||||||
uint32_t rstype = getRsItemId(data);
|
uint32_t rstype = getRsItemId(data);
|
||||||
|
|
||||||
if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) ||
|
if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || (RS_SERVICE_GXS_TYPE_GXSCIRCLE != getRsItemService(rstype)))
|
||||||
(RS_SERVICE_GXS_TYPE_GXSCIRCLE != getRsItemService(rstype)))
|
|
||||||
{
|
{
|
||||||
return NULL; /* wrong type */
|
return NULL; /* wrong type */
|
||||||
}
|
}
|
||||||
|
@ -88,6 +97,9 @@ RsItem* RsGxsCircleSerialiser::deserialise(void* data, uint32_t* size)
|
||||||
case RS_PKT_SUBTYPE_GXSCIRCLE_MSG_ITEM:
|
case RS_PKT_SUBTYPE_GXSCIRCLE_MSG_ITEM:
|
||||||
return deserialiseGxsCircleMsgItem(data, size);
|
return deserialiseGxsCircleMsgItem(data, size);
|
||||||
break;
|
break;
|
||||||
|
case RS_PKT_SUBTYPE_GXSCIRCLE_SUBSCRIPTION_REQUEST_ITEM:
|
||||||
|
return deserialiseGxsCircleSubscriptionRequestItem(data, size);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
#ifdef CIRCLE_DEBUG
|
#ifdef CIRCLE_DEBUG
|
||||||
std::cerr << "RsGxsCircleSerialiser::deserialise(): unknown subtype";
|
std::cerr << "RsGxsCircleSerialiser::deserialise(): unknown subtype";
|
||||||
|
@ -104,6 +116,25 @@ RsItem* RsGxsCircleSerialiser::deserialise(void* data, uint32_t* size)
|
||||||
/*****************************************************************************************/
|
/*****************************************************************************************/
|
||||||
/*****************************************************************************************/
|
/*****************************************************************************************/
|
||||||
|
|
||||||
|
void RsGxsCircleSubscriptionRequestItem::clear()
|
||||||
|
{
|
||||||
|
time_stamp = 0 ;
|
||||||
|
time_out = 0 ;
|
||||||
|
subscription_type = SUBSCRIPTION_REQUEST_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& RsGxsCircleSubscriptionRequestItem::print(std::ostream& out, uint16_t indent)
|
||||||
|
{
|
||||||
|
printRsItemBase(out, "RsGxsCircleSubscriptionRequestItem", indent);
|
||||||
|
uint16_t int_Indent = indent + 2;
|
||||||
|
|
||||||
|
printRsItemBase(out, "time stmp: ", indent); out << time_stamp ;
|
||||||
|
printRsItemBase(out, "time out : ", indent); out << time_out ;
|
||||||
|
printRsItemBase(out, "Subs type: ", indent); out << subscription_type ;
|
||||||
|
|
||||||
|
printRsItemEnd(out ,"RsGxsCircleSubscriptionRequestItem", indent);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
void RsGxsCircleGroupItem::clear()
|
void RsGxsCircleGroupItem::clear()
|
||||||
{
|
{
|
||||||
|
@ -176,6 +207,16 @@ std::ostream& RsGxsCircleGroupItem::print(std::ostream& out, uint16_t indent)
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t RsGxsCircleSerialiser::sizeGxsCircleSubscriptionRequestItem(RsGxsCircleSubscriptionRequestItem * /* item */)
|
||||||
|
{
|
||||||
|
uint32_t s=8 ; // header
|
||||||
|
|
||||||
|
s += 4 ; // time_stamp serialised as uint32_t;
|
||||||
|
s += 4 ; // time_out serialised as uint32_t;
|
||||||
|
s += 1 ; // subscription_type ;
|
||||||
|
|
||||||
|
return s ;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t RsGxsCircleSerialiser::sizeGxsCircleGroupItem(RsGxsCircleGroupItem *item)
|
uint32_t RsGxsCircleSerialiser::sizeGxsCircleGroupItem(RsGxsCircleGroupItem *item)
|
||||||
{
|
{
|
||||||
|
@ -188,6 +229,54 @@ uint32_t RsGxsCircleSerialiser::sizeGxsCircleGroupItem(RsGxsCircleGroupItem *ite
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RsGxsCircleSerialiser::serialiseGxsCircleSubscriptionRequestItem(RsGxsCircleSubscriptionRequestItem *item, void *data, uint32_t *size)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef CIRCLE_DEBUG
|
||||||
|
std::cerr << "RsGxsCircleSerialiser::serialiseGxsCircleSubscriptionRequestItem()" << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint32_t tlvsize = sizeGxsCircleSubscriptionRequestItem(item);
|
||||||
|
uint32_t offset = 0;
|
||||||
|
|
||||||
|
if(*size < tlvsize)
|
||||||
|
{
|
||||||
|
#ifdef CIRCLE_DEBUG
|
||||||
|
std::cerr << "RsGxsCircleSerialiser::serialiseGxsCircleSubscriptionRequestItem()" << std::endl;
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*size = tlvsize;
|
||||||
|
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize);
|
||||||
|
|
||||||
|
/* skip the header */
|
||||||
|
offset += 8;
|
||||||
|
|
||||||
|
/* GxsCircleGroupItem */
|
||||||
|
ok &= setRawUInt32(data,tlvsize,&offset,item->time_stamp) ;
|
||||||
|
ok &= setRawUInt32(data,tlvsize,&offset,item->time_out) ;
|
||||||
|
ok &= setRawUInt8(data,tlvsize,&offset,item->subscription_type) ;
|
||||||
|
|
||||||
|
if(offset != tlvsize)
|
||||||
|
{
|
||||||
|
//#ifdef CIRCLE_DEBUG
|
||||||
|
std::cerr << "RsGxsCircleSerialiser::serialiseGxsCircleSubscriptionRequestItem() FAIL Size Error! " << std::endl;
|
||||||
|
//#endif
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//#ifdef CIRCLE_DEBUG
|
||||||
|
if (!ok)
|
||||||
|
std::cerr << "RsGxsCircleSerialiser::serialiseGxsCircleSubscriptionRequestItem() NOK" << std::endl;
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
bool RsGxsCircleSerialiser::serialiseGxsCircleGroupItem(RsGxsCircleGroupItem *item, void *data, uint32_t *size)
|
bool RsGxsCircleSerialiser::serialiseGxsCircleGroupItem(RsGxsCircleGroupItem *item, void *data, uint32_t *size)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -238,6 +327,72 @@ bool RsGxsCircleSerialiser::serialiseGxsCircleGroupItem(RsGxsCircleGroupItem *it
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RsGxsCircleSubscriptionRequestItem *RsGxsCircleSerialiser::deserialiseGxsCircleSubscriptionRequestItem(void *data, uint32_t *size)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef CIRCLE_DEBUG
|
||||||
|
std::cerr << "RsGxsCircleSerialiser::deserialiseGxsCircleSubscriptionRequestItem()" << std::endl;
|
||||||
|
#endif
|
||||||
|
/* get the type and size */
|
||||||
|
uint32_t rstype = getRsItemId(data);
|
||||||
|
uint32_t rssize = getRsItemSize(data);
|
||||||
|
|
||||||
|
uint32_t offset = 0;
|
||||||
|
|
||||||
|
|
||||||
|
if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) ||
|
||||||
|
(RS_SERVICE_GXS_TYPE_GXSCIRCLE != getRsItemService(rstype)) ||
|
||||||
|
(RS_PKT_SUBTYPE_GXSCIRCLE_SUBSCRIPTION_REQUEST_ITEM != getRsItemSubType(rstype)))
|
||||||
|
{
|
||||||
|
#ifdef CIRCLE_DEBUG
|
||||||
|
std::cerr << "RsGxsCircleSerialiser::deserialiseGxsCircleSubscriptionRequestItem() FAIL wrong type" << std::endl;
|
||||||
|
#endif
|
||||||
|
return NULL; /* wrong type */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*size < rssize) /* check size */
|
||||||
|
{
|
||||||
|
#ifdef CIRCLE_DEBUG
|
||||||
|
std::cerr << "RsGxsCircleSerialiser::deserialiseGxsCircleSubscriptionRequestItem() FAIL wrong size" << std::endl;
|
||||||
|
#endif
|
||||||
|
return NULL; /* not enough data */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the packet length */
|
||||||
|
*size = rssize;
|
||||||
|
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
RsGxsCircleSubscriptionRequestItem* item = new RsGxsCircleSubscriptionRequestItem();
|
||||||
|
/* skip the header */
|
||||||
|
offset += 8;
|
||||||
|
|
||||||
|
uint32_t tmp ;
|
||||||
|
ok &= getRawUInt32(data,rssize,&offset,&tmp) ; item->time_stamp = tmp ;
|
||||||
|
ok &= getRawUInt32(data,rssize,&offset,&tmp) ; item->time_out = tmp ;
|
||||||
|
ok &= getRawUInt8(data,rssize,&offset,&item->subscription_type) ;
|
||||||
|
|
||||||
|
if (offset != rssize)
|
||||||
|
{
|
||||||
|
#ifdef CIRCLE_DEBUG
|
||||||
|
std::cerr << "RsGxsCircleSerialiser::deserialiseGxsCircleSubscriptionRequestItem() FAIL size mismatch" << std::endl;
|
||||||
|
#endif
|
||||||
|
/* error */
|
||||||
|
delete item;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
#ifdef CIRCLE_DEBUG
|
||||||
|
std::cerr << "RsGxsCircleSerialiser::deserialiseGxsCircleSubscriptionRequestItem() NOK" << std::endl;
|
||||||
|
#endif
|
||||||
|
delete item;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
RsGxsCircleGroupItem* RsGxsCircleSerialiser::deserialiseGxsCircleGroupItem(void *data, uint32_t *size)
|
RsGxsCircleGroupItem* RsGxsCircleSerialiser::deserialiseGxsCircleGroupItem(void *data, uint32_t *size)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -39,11 +39,14 @@
|
||||||
|
|
||||||
const uint8_t RS_PKT_SUBTYPE_GXSCIRCLE_GROUP_ITEM = 0x02;
|
const uint8_t RS_PKT_SUBTYPE_GXSCIRCLE_GROUP_ITEM = 0x02;
|
||||||
const uint8_t RS_PKT_SUBTYPE_GXSCIRCLE_MSG_ITEM = 0x03;
|
const uint8_t RS_PKT_SUBTYPE_GXSCIRCLE_MSG_ITEM = 0x03;
|
||||||
|
const uint8_t RS_PKT_SUBTYPE_GXSCIRCLE_SUBSCRIPTION_REQUEST_ITEM = 0x04;
|
||||||
|
|
||||||
const uint16_t GXSCIRCLE_PGPIDSET = 0x0001;
|
const uint16_t GXSCIRCLE_PGPIDSET = 0x0001;
|
||||||
const uint16_t GXSCIRCLE_GXSIDSET = 0x0002;
|
const uint16_t GXSCIRCLE_GXSIDSET = 0x0002;
|
||||||
const uint16_t GXSCIRCLE_SUBCIRCLESET = 0x0003;
|
const uint16_t GXSCIRCLE_SUBCIRCLESET = 0x0003;
|
||||||
|
|
||||||
|
// These classes are a mess. Needs proper item serialisation etc.
|
||||||
|
|
||||||
class RsGxsCircleGroupItem : public RsGxsGrpItem
|
class RsGxsCircleGroupItem : public RsGxsGrpItem
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -83,6 +86,27 @@ public:
|
||||||
RsGxsCircleMsg msg;
|
RsGxsCircleMsg msg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class RsGxsCircleSubscriptionRequestItem: public RsGxsMsgItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
RsGxsCircleSubscriptionRequestItem() : RsGxsMsgItem(RS_SERVICE_GXS_TYPE_GXSCIRCLE, RS_PKT_SUBTYPE_GXSCIRCLE_SUBSCRIPTION_REQUEST_ITEM) { }
|
||||||
|
virtual ~RsGxsCircleSubscriptionRequestItem() {}
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
std::ostream &print(std::ostream &out, uint16_t indent = 0);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SUBSCRIPTION_REQUEST_UNKNOWN = 0x00,
|
||||||
|
SUBSCRIPTION_REQUEST_SUBSCRIBE = 0x01,
|
||||||
|
SUBSCRIPTION_REQUEST_UNSUBSCRIBE = 0x02
|
||||||
|
};
|
||||||
|
|
||||||
|
time_t time_stamp ;
|
||||||
|
time_t time_out ;
|
||||||
|
uint8_t subscription_type ;
|
||||||
|
};
|
||||||
|
|
||||||
class RsGxsCircleSerialiser : public RsSerialType
|
class RsGxsCircleSerialiser : public RsSerialType
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -98,6 +122,10 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
uint32_t sizeGxsCircleSubscriptionRequestItem(RsGxsCircleSubscriptionRequestItem *item);
|
||||||
|
bool serialiseGxsCircleSubscriptionRequestItem (RsGxsCircleSubscriptionRequestItem *item, void *data, uint32_t *size);
|
||||||
|
RsGxsCircleSubscriptionRequestItem * deserialiseGxsCircleSubscriptionRequestItem(void *data, uint32_t *size);
|
||||||
|
|
||||||
uint32_t sizeGxsCircleGroupItem(RsGxsCircleGroupItem *item);
|
uint32_t sizeGxsCircleGroupItem(RsGxsCircleGroupItem *item);
|
||||||
bool serialiseGxsCircleGroupItem (RsGxsCircleGroupItem *item, void *data, uint32_t *size);
|
bool serialiseGxsCircleGroupItem (RsGxsCircleGroupItem *item, void *data, uint32_t *size);
|
||||||
RsGxsCircleGroupItem * deserialiseGxsCircleGroupItem(void *data, uint32_t *size);
|
RsGxsCircleGroupItem * deserialiseGxsCircleGroupItem(void *data, uint32_t *size);
|
||||||
|
|
|
@ -993,7 +993,7 @@ std::string SSGxsChannelGroup::save() const
|
||||||
if(!mDownloadDirectory.empty())
|
if(!mDownloadDirectory.empty())
|
||||||
{
|
{
|
||||||
std::string encoded_str ;
|
std::string encoded_str ;
|
||||||
Radix64::encode(mDownloadDirectory.c_str(),mDownloadDirectory.length(),encoded_str);
|
Radix64::encode((unsigned char*)mDownloadDirectory.c_str(),mDownloadDirectory.length(),encoded_str);
|
||||||
|
|
||||||
output += " {P:" + encoded_str + "}";
|
output += " {P:" + encoded_str + "}";
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,9 +27,13 @@
|
||||||
#include "serialiser/rsgxscircleitems.h"
|
#include "serialiser/rsgxscircleitems.h"
|
||||||
#include "retroshare/rsgxsflags.h"
|
#include "retroshare/rsgxsflags.h"
|
||||||
#include "util/rsrandom.h"
|
#include "util/rsrandom.h"
|
||||||
|
#include "util/rsdir.h"
|
||||||
|
#include "util/radix64.h"
|
||||||
#include "util/rsstring.h"
|
#include "util/rsstring.h"
|
||||||
|
|
||||||
#include "pgp/pgpauxutils.h"
|
#include "pgp/pgpauxutils.h"
|
||||||
|
#include "retroshare/rsgxscircles.h"
|
||||||
|
#include "retroshare/rspeers.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -73,6 +77,7 @@ RsGxsCircles *rsGxsCircles = NULL;
|
||||||
|
|
||||||
#define CIRCLEREQ_CACHELOAD 0x0001
|
#define CIRCLEREQ_CACHELOAD 0x0001
|
||||||
#define CIRCLEREQ_CIRCLE_LIST 0x0002
|
#define CIRCLEREQ_CIRCLE_LIST 0x0002
|
||||||
|
#define CIRCLEREQ_MESSAGE_DATA 0x0003
|
||||||
|
|
||||||
//#define CIRCLEREQ_PGPHASH 0x0010
|
//#define CIRCLEREQ_PGPHASH 0x0010
|
||||||
//#define CIRCLEREQ_REPUTATION 0x0020
|
//#define CIRCLEREQ_REPUTATION 0x0020
|
||||||
|
@ -97,6 +102,8 @@ RsGxsCircles *rsGxsCircles = NULL;
|
||||||
#define GXSID_LOAD_CYCLE 10 // GXSID completes a load in this period.
|
#define GXSID_LOAD_CYCLE 10 // GXSID completes a load in this period.
|
||||||
|
|
||||||
#define MIN_CIRCLE_LOAD_GAP 5
|
#define MIN_CIRCLE_LOAD_GAP 5
|
||||||
|
#define GXS_CIRCLE_DELAY_TO_FORCE_MEMBERSHIP_UPDATE 60 // re-check every 1 mins. Normally this shouldn't be necessary since notifications inform abotu new messages.
|
||||||
|
#define GXS_CIRCLE_DELAY_TO_CHECK_MEMBERSHIP_UPDATE 60 // re-check every 1 mins. Normally this shouldn't be necessary since notifications inform abotu new messages.
|
||||||
|
|
||||||
/********************************************************************************/
|
/********************************************************************************/
|
||||||
/******************* Startup / Tick ******************************************/
|
/******************* Startup / Tick ******************************************/
|
||||||
|
@ -115,6 +122,7 @@ p3GxsCircles::p3GxsCircles(RsGeneralDataService *gds, RsNetworkExchangeService *
|
||||||
{
|
{
|
||||||
// Kick off Cache Testing, + Others.
|
// Kick off Cache Testing, + Others.
|
||||||
//RsTickEvent::schedule_in(CIRCLE_EVENT_CACHETEST, CACHETEST_PERIOD);
|
//RsTickEvent::schedule_in(CIRCLE_EVENT_CACHETEST, CACHETEST_PERIOD);
|
||||||
|
mLastCacheMembershipUpdateTS = 0 ;
|
||||||
|
|
||||||
RsTickEvent::schedule_now(CIRCLE_EVENT_LOADIDS);
|
RsTickEvent::schedule_now(CIRCLE_EVENT_LOADIDS);
|
||||||
|
|
||||||
|
@ -123,6 +131,13 @@ p3GxsCircles::p3GxsCircles(RsGeneralDataService *gds, RsNetworkExchangeService *
|
||||||
mDummyIdToken = 0;
|
mDummyIdToken = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool allowedGxsIdFlagTest(uint32_t subscription_flags,bool group_is_self_restricted)
|
||||||
|
{
|
||||||
|
if(group_is_self_restricted)
|
||||||
|
return (subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST) && (subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_KEY_AVAILABLE);
|
||||||
|
else
|
||||||
|
return (subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST) && (subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED) && (subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_KEY_AVAILABLE);
|
||||||
|
}
|
||||||
|
|
||||||
const std::string GXS_CIRCLES_APP_NAME = "gxscircle";
|
const std::string GXS_CIRCLES_APP_NAME = "gxscircle";
|
||||||
const uint16_t GXS_CIRCLES_APP_MAJOR_VERSION = 1;
|
const uint16_t GXS_CIRCLES_APP_MAJOR_VERSION = 1;
|
||||||
|
@ -169,6 +184,13 @@ void p3GxsCircles::service_tick()
|
||||||
{
|
{
|
||||||
RsTickEvent::tick_events();
|
RsTickEvent::tick_events();
|
||||||
GxsTokenQueue::checkRequests(); // GxsTokenQueue handles all requests.
|
GxsTokenQueue::checkRequests(); // GxsTokenQueue handles all requests.
|
||||||
|
|
||||||
|
time_t now = time(NULL);
|
||||||
|
if(now > mLastCacheMembershipUpdateTS + GXS_CIRCLE_DELAY_TO_CHECK_MEMBERSHIP_UPDATE)
|
||||||
|
{
|
||||||
|
p3GxsCircles::checkCircleCacheForMembershipUpdate();
|
||||||
|
mLastCacheMembershipUpdateTS = now ;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,21 +206,19 @@ void p3GxsCircles::notifyChanges(std::vector<RsGxsNotify *> &changes)
|
||||||
{
|
{
|
||||||
RsGxsGroupChange *groupChange = dynamic_cast<RsGxsGroupChange *>(*it);
|
RsGxsGroupChange *groupChange = dynamic_cast<RsGxsGroupChange *>(*it);
|
||||||
RsGxsMsgChange *msgChange = dynamic_cast<RsGxsMsgChange *>(*it);
|
RsGxsMsgChange *msgChange = dynamic_cast<RsGxsMsgChange *>(*it);
|
||||||
|
|
||||||
if (msgChange && !msgChange->metaChange())
|
if (msgChange && !msgChange->metaChange())
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_CIRCLES
|
#ifdef DEBUG_CIRCLES
|
||||||
std::cerr << " Found Message Change Notification";
|
std::cerr << " Found circle Message Change Notification" << std::endl;
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
#endif
|
||||||
|
for(std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >::iterator mit = msgChange->msgChangeMap.begin(); mit != msgChange->msgChangeMap.end(); ++mit)
|
||||||
std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > &msgChangeMap = msgChange->msgChangeMap;
|
|
||||||
std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >::iterator mit;
|
|
||||||
for(mit = msgChangeMap.begin(); mit != msgChangeMap.end(); ++mit)
|
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_CIRCLES
|
#ifdef DEBUG_CIRCLES
|
||||||
std::cerr << " Msgs for Group: " << mit->first;
|
std::cerr << " Msgs for Group: " << mit->first << std::endl;
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
#endif
|
||||||
|
for(std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >::const_iterator it2(msgChange->msgChangeMap.begin());it2!=msgChange->msgChangeMap.end();++it2)
|
||||||
|
force_cache_reload(RsGxsCircleId(it2->first)) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,13 +226,9 @@ void p3GxsCircles::notifyChanges(std::vector<RsGxsNotify *> &changes)
|
||||||
if (groupChange && !groupChange->metaChange())
|
if (groupChange && !groupChange->metaChange())
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_CIRCLES
|
#ifdef DEBUG_CIRCLES
|
||||||
std::cerr << " Found Group Change Notification";
|
std::cerr << " Found Group Change Notification" << std::endl;
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
#endif
|
||||||
|
for(std::list<RsGxsGroupId>::iterator git = groupChange->mGrpIdList.begin(); git != groupChange->mGrpIdList.end(); ++git)
|
||||||
std::list<RsGxsGroupId> &groupList = groupChange->mGrpIdList;
|
|
||||||
std::list<RsGxsGroupId>::iterator git;
|
|
||||||
for(git = groupList.begin(); git != groupList.end(); ++git)
|
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_CIRCLES
|
#ifdef DEBUG_CIRCLES
|
||||||
std::cerr << " Incoming Group: " << *git << ". Forcing cache load." << std::endl;
|
std::cerr << " Incoming Group: " << *git << ". Forcing cache load." << std::endl;
|
||||||
|
@ -221,6 +237,7 @@ void p3GxsCircles::notifyChanges(std::vector<RsGxsNotify *> &changes)
|
||||||
// for new circles we need to add them to the list.
|
// for new circles we need to add them to the list.
|
||||||
// we don't know the type of this circle here
|
// we don't know the type of this circle here
|
||||||
// original behavior was to add all ids to the external ids list
|
// original behavior was to add all ids to the external ids list
|
||||||
|
|
||||||
addCircleIdToList(RsGxsCircleId(*git), 0);
|
addCircleIdToList(RsGxsCircleId(*git), 0);
|
||||||
|
|
||||||
// reset the cached circle data for this id
|
// reset the cached circle data for this id
|
||||||
|
@ -266,12 +283,26 @@ bool p3GxsCircles:: getCircleDetails(const RsGxsCircleId &id, RsGxsCircleDetails
|
||||||
details.mCircleName = data.mCircleName;
|
details.mCircleName = data.mCircleName;
|
||||||
|
|
||||||
details.mCircleType = data.mCircleType;
|
details.mCircleType = data.mCircleType;
|
||||||
details.mIsExternal = data.mIsExternal;
|
|
||||||
|
|
||||||
details.mAllowedAnonPeers = data.mAllowedAnonPeers;
|
details.mAllowedNodes = data.mAllowedNodes;
|
||||||
details.mAllowedSignedPeers = data.mAllowedSignedPeers;
|
details.mSubscriptionFlags.clear();
|
||||||
|
details.mAllowedGxsIds.clear();
|
||||||
|
details.mAmIAllowed = false ;
|
||||||
|
|
||||||
|
for(std::map<RsGxsId,RsGxsCircleMembershipStatus>::const_iterator it(data.mMembershipStatus.begin());it!=data.mMembershipStatus.end();++it)
|
||||||
|
{
|
||||||
|
details.mSubscriptionFlags[it->first] = it->second.subscription_flags ;
|
||||||
|
|
||||||
|
if(it->second.subscription_flags == GXS_EXTERNAL_CIRCLE_FLAGS_ALLOWED)
|
||||||
|
{
|
||||||
|
details.mAllowedGxsIds.insert(it->first) ;
|
||||||
|
|
||||||
|
if(rsIdentity->isOwnId(it->first))
|
||||||
|
details.mAmIAllowed = true ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
details.mAmIAllowed = data.mAmIAllowed ;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -391,30 +422,34 @@ bool p3GxsCircles::recipients(const RsGxsCircleId &circleId, std::list<RsPgpId>&
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool p3GxsCircles::isRecipient(const RsGxsCircleId &circleId, const RsGxsId& id)
|
bool p3GxsCircles::isRecipient(const RsGxsCircleId &circleId, const RsGxsGroupId& destination_group, const RsGxsId& id)
|
||||||
{
|
{
|
||||||
RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/
|
RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/
|
||||||
if (mCircleCache.is_cached(circleId))
|
if (mCircleCache.is_cached(circleId))
|
||||||
{
|
{
|
||||||
const RsGxsCircleCache &data = mCircleCache.ref(circleId);
|
const RsGxsCircleCache &data = mCircleCache.ref(circleId);
|
||||||
return data.isAllowedPeer(id);
|
return data.isAllowedPeer(id,destination_group);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool p3GxsCircles::recipients(const RsGxsCircleId& circleId, std::list<RsGxsId>& gxs_ids)
|
// This function uses the destination group for the transaction in order to decide which list of
|
||||||
|
// keys to ecnrypt to. When sending to a self-restricted group, the list of recipients is extended to
|
||||||
|
// the admin list rather than just the members list.
|
||||||
|
|
||||||
|
bool p3GxsCircles::recipients(const RsGxsCircleId& circleId, const RsGxsGroupId& dest_group, std::list<RsGxsId>& gxs_ids)
|
||||||
{
|
{
|
||||||
RsGxsCircleDetails details ;
|
gxs_ids.clear() ;
|
||||||
|
|
||||||
if(!getCircleDetails(circleId, details))
|
RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/
|
||||||
|
if (!mCircleCache.is_cached(circleId))
|
||||||
return false ;
|
return false ;
|
||||||
|
|
||||||
for(std::set<RsGxsId>::const_iterator it(details.mAllowedAnonPeers.begin());it!=details.mAllowedAnonPeers.end();++it)
|
const RsGxsCircleCache& cache = mCircleCache.ref(circleId);
|
||||||
gxs_ids.push_back(*it) ;
|
|
||||||
|
|
||||||
for(std::map<RsPgpId,std::set<RsGxsId> >::const_iterator it(details.mAllowedSignedPeers.begin());it!=details.mAllowedSignedPeers.end();++it)
|
for(std::map<RsGxsId,RsGxsCircleMembershipStatus>::const_iterator it(cache.mMembershipStatus.begin());it!=cache.mMembershipStatus.end();++it)
|
||||||
for(std::set<RsGxsId>::const_iterator it2(it->second.begin());it2!=it->second.end();++it2)
|
if(allowedGxsIdFlagTest(it->second.subscription_flags, RsGxsCircleId(dest_group) == circleId))
|
||||||
gxs_ids.push_back(*it2) ;
|
gxs_ids.push_back(it->first) ;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -529,10 +564,10 @@ RsGxsCircleCache::RsGxsCircleCache()
|
||||||
{
|
{
|
||||||
mCircleType = GXS_CIRCLE_TYPE_EXTERNAL;
|
mCircleType = GXS_CIRCLE_TYPE_EXTERNAL;
|
||||||
mIsExternal = true;
|
mIsExternal = true;
|
||||||
mAmIAllowed = false ;
|
|
||||||
mUpdateTime = 0;
|
mUpdateTime = 0;
|
||||||
mGroupStatus = 0;
|
mGroupStatus = 0;
|
||||||
mGroupSubscribeFlags = 0;
|
mGroupSubscribeFlags = 0;
|
||||||
|
mLastUpdatedMembershipTS = 0 ;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -550,7 +585,18 @@ bool RsGxsCircleCache::loadBaseCircle(const RsGxsCircleGroup &circle)
|
||||||
mIsExternal = (mCircleType != GXS_CIRCLE_TYPE_LOCAL);
|
mIsExternal = (mCircleType != GXS_CIRCLE_TYPE_LOCAL);
|
||||||
mGroupStatus = circle.mMeta.mGroupStatus;
|
mGroupStatus = circle.mMeta.mGroupStatus;
|
||||||
mGroupSubscribeFlags = circle.mMeta.mSubscribeFlags;
|
mGroupSubscribeFlags = circle.mMeta.mSubscribeFlags;
|
||||||
mAmIAllowed = false ; // by default. Will be computed later.
|
mOriginator = circle.mMeta.mOriginator ;
|
||||||
|
|
||||||
|
mAllowedNodes = circle.mLocalFriends ;
|
||||||
|
|
||||||
|
mMembershipStatus.clear() ;
|
||||||
|
|
||||||
|
for(std::set<RsGxsId>::const_iterator it(circle.mInvitedMembers.begin());it!=circle.mInvitedMembers.end();++it)
|
||||||
|
{
|
||||||
|
RsGxsCircleMembershipStatus& s(mMembershipStatus[*it]) ;
|
||||||
|
s.last_subscription_TS = 0 ;
|
||||||
|
s.subscription_flags = GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST ;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_CIRCLES
|
#ifdef DEBUG_CIRCLES
|
||||||
std::cerr << "RsGxsCircleCache::loadBaseCircle(" << mCircleId << ")";
|
std::cerr << "RsGxsCircleCache::loadBaseCircle(" << mCircleId << ")";
|
||||||
|
@ -576,51 +622,33 @@ bool RsGxsCircleCache::loadSubCircle(const RsGxsCircleCache &subcircle)
|
||||||
|
|
||||||
bool RsGxsCircleCache::getAllowedPeersList(std::list<RsPgpId>& friendlist) const
|
bool RsGxsCircleCache::getAllowedPeersList(std::list<RsPgpId>& friendlist) const
|
||||||
{
|
{
|
||||||
std::map<RsPgpId, std::set<RsGxsId> >::const_iterator it;
|
friendlist.clear() ;
|
||||||
for(it = mAllowedSignedPeers.begin(); it != mAllowedSignedPeers.end(); ++it)
|
|
||||||
{
|
for(std::set<RsPgpId>::const_iterator it = mAllowedNodes.begin(); it != mAllowedNodes.end(); ++it)
|
||||||
friendlist.push_back(it->first);
|
friendlist.push_back(*it) ;
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RsGxsCircleCache::isAllowedPeer(const RsGxsId &id) const
|
bool RsGxsCircleCache::isAllowedPeer(const RsGxsId& id,const RsGxsGroupId& destination_group) const
|
||||||
{
|
{
|
||||||
if(mUnprocessedPeers.find(id) != mUnprocessedPeers.end())
|
std::map<RsGxsId,RsGxsCircleMembershipStatus>::const_iterator it = mMembershipStatus.find(id) ;
|
||||||
return true ;
|
|
||||||
|
|
||||||
if(mAllowedAnonPeers.find(id) != mAllowedAnonPeers.end())
|
|
||||||
return true ;
|
|
||||||
|
|
||||||
for(std::map<RsPgpId,std::set<RsGxsId> >::const_iterator it = mAllowedSignedPeers.begin();it!=mAllowedSignedPeers.end();++it)
|
|
||||||
if(it->second.find(id) != it->second.end())
|
|
||||||
return true ;
|
|
||||||
|
|
||||||
|
if(it == mMembershipStatus.end())
|
||||||
return false ;
|
return false ;
|
||||||
|
|
||||||
|
return allowedGxsIdFlagTest(it->second.subscription_flags, RsGxsGroupId(mCircleId) == destination_group) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RsGxsCircleCache::isAllowedPeer(const RsPgpId &id) const
|
bool RsGxsCircleCache::isAllowedPeer(const RsPgpId &id) const
|
||||||
{
|
{
|
||||||
std::map<RsPgpId, std::set<RsGxsId> >::const_iterator it = mAllowedSignedPeers.find(id);
|
return mAllowedNodes.find(id) != mAllowedNodes.end() ;
|
||||||
if (it != mAllowedSignedPeers.end())
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RsGxsCircleCache::addAllowedPeer(const RsPgpId &pgpId, const RsGxsId &gxsId)
|
|
||||||
{
|
|
||||||
/* created if doesn't exist */
|
|
||||||
mAllowedSignedPeers[pgpId].insert(gxsId);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool RsGxsCircleCache::addLocalFriend(const RsPgpId &pgpId)
|
bool RsGxsCircleCache::addLocalFriend(const RsPgpId &pgpId)
|
||||||
{
|
{
|
||||||
/* empty list as no GxsID associated */
|
/* empty list as no GxsID associated */
|
||||||
mAllowedSignedPeers.insert(std::make_pair(pgpId,std::set<RsGxsId>()));
|
mAllowedNodes.insert(pgpId) ;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -873,8 +901,7 @@ bool p3GxsCircles::cache_request_load(const RsGxsCircleId &id)
|
||||||
{
|
{
|
||||||
if (age < MIN_CIRCLE_LOAD_GAP)
|
if (age < MIN_CIRCLE_LOAD_GAP)
|
||||||
{
|
{
|
||||||
RsTickEvent::schedule_in(CIRCLE_EVENT_CACHELOAD,
|
RsTickEvent::schedule_in(CIRCLE_EVENT_CACHELOAD, MIN_CIRCLE_LOAD_GAP - age);
|
||||||
MIN_CIRCLE_LOAD_GAP - age);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -937,10 +964,15 @@ bool p3GxsCircles::cache_load_for_token(uint32_t token)
|
||||||
#endif // DEBUG_CIRCLES
|
#endif // DEBUG_CIRCLES
|
||||||
|
|
||||||
std::vector<RsGxsGrpItem*> grpData;
|
std::vector<RsGxsGrpItem*> grpData;
|
||||||
bool ok = RsGenExchange::getGroupData(token, grpData);
|
|
||||||
|
|
||||||
if(ok)
|
if(!RsGenExchange::getGroupData(token, grpData))
|
||||||
{
|
{
|
||||||
|
std::cerr << "p3GxsCircles::cache_load_for_token() ERROR no data";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<RsGxsGrpItem*>::iterator vit = grpData.begin();
|
std::vector<RsGxsGrpItem*>::iterator vit = grpData.begin();
|
||||||
|
|
||||||
for(; vit != grpData.end(); ++vit)
|
for(; vit != grpData.end(); ++vit)
|
||||||
|
@ -963,9 +995,12 @@ bool p3GxsCircles::cache_load_for_token(uint32_t token)
|
||||||
RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/
|
RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/
|
||||||
|
|
||||||
/* should already have a LoadingCache entry */
|
/* should already have a LoadingCache entry */
|
||||||
RsGxsCircleId id = RsGxsCircleId(item->meta.mGroupId.toStdString());
|
RsGxsCircleId id = RsGxsCircleId(item->meta.mGroupId) ;
|
||||||
std::map<RsGxsCircleId, RsGxsCircleCache>::iterator it;
|
|
||||||
it = mLoadingCache.find(id);
|
// (cyril) I'm not sure this logic is needed. The token system would avoid duplicates normally.
|
||||||
|
|
||||||
|
std::map<RsGxsCircleId, RsGxsCircleCache>::iterator it = mLoadingCache.find(id);
|
||||||
|
|
||||||
if (it == mLoadingCache.end())
|
if (it == mLoadingCache.end())
|
||||||
{
|
{
|
||||||
std::cerr << "p3GxsCircles::cache_load_for_token() Load ERROR: ";
|
std::cerr << "p3GxsCircles::cache_load_for_token() Load ERROR: ";
|
||||||
|
@ -977,101 +1012,82 @@ bool p3GxsCircles::cache_load_for_token(uint32_t token)
|
||||||
}
|
}
|
||||||
|
|
||||||
RsGxsCircleCache& cache = it->second;
|
RsGxsCircleCache& cache = it->second;
|
||||||
|
|
||||||
cache.loadBaseCircle(group);
|
cache.loadBaseCircle(group);
|
||||||
cache.mOriginator = item->meta.mOriginator ;
|
|
||||||
cache.mAmIAllowed = false;
|
|
||||||
delete item;
|
delete item;
|
||||||
|
|
||||||
|
if(locked_processLoadingCacheEntry(it->second))
|
||||||
|
{
|
||||||
|
std::cerr << " All peers available. Moving to cache..." << std::endl;
|
||||||
|
mLoadingCache.erase(it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << " Unprocessed peers. Requesting reload..." << std::endl;
|
||||||
|
|
||||||
bool isComplete = true;
|
/* schedule event to try reload gxsIds */
|
||||||
|
RsTickEvent::schedule_in(CIRCLE_EVENT_RELOADIDS, GXSID_LOAD_CYCLE, id.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method parses the cache entry and makes sure that all ids are known. If not, requests the missing ids
|
||||||
|
// when done, the entry is removed from mLoadingCache
|
||||||
|
|
||||||
|
bool p3GxsCircles::locked_processLoadingCacheEntry(RsGxsCircleCache& cache)
|
||||||
|
{
|
||||||
bool isUnprocessedPeers = false;
|
bool isUnprocessedPeers = false;
|
||||||
|
|
||||||
|
|
||||||
if (cache.mIsExternal)
|
if (cache.mIsExternal)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_CIRCLES
|
#ifdef DEBUG_CIRCLES
|
||||||
std::cerr << " Loading External Circle" << std::endl;
|
std::cerr << "Processing External Circle " << cache.mCircleId << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::set<RsGxsId> &peers = group.mInvitedMembers;
|
|
||||||
std::set<RsGxsId>::const_iterator pit;
|
|
||||||
|
|
||||||
std::list<RsGxsId> myOwnIds;
|
|
||||||
|
|
||||||
if(rsIdentity->getOwnIds(myOwnIds))
|
|
||||||
{
|
|
||||||
bool ownIdInCircle = false ;
|
|
||||||
|
|
||||||
for(std::list<RsGxsId>::const_iterator it(myOwnIds.begin());it!=myOwnIds.end() && !ownIdInCircle;++it)
|
|
||||||
ownIdInCircle = ownIdInCircle || (peers.find(*it) != peers.end()) ;
|
|
||||||
|
|
||||||
#ifdef DEBUG_CIRCLES
|
|
||||||
std::cerr << " own ID in circle: " << ownIdInCircle << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cache.mAmIAllowed = ownIdInCircle;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cerr << " own ids not loaded yet." << std::endl;
|
|
||||||
isComplete = false;
|
|
||||||
isUnprocessedPeers = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// need to trigger the searches.
|
// need to trigger the searches.
|
||||||
for(pit = peers.begin(); pit != peers.end(); ++pit)
|
for(std::map<RsGxsId,RsGxsCircleMembershipStatus>::iterator pit = cache.mMembershipStatus.begin(); pit != cache.mMembershipStatus.end(); ++pit)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_CIRCLES
|
#ifdef DEBUG_CIRCLES
|
||||||
std::cerr << " Invited Member: " << *pit ;
|
std::cerr << " Member status: " << pit->first << " : " << pit->second.subscription_flags;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* check cache */
|
/* check cache */
|
||||||
if (mIdentities->haveKey(*pit))
|
if(!(pit->second.subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_KEY_AVAILABLE))
|
||||||
{
|
if(mIdentities->haveKey(pit->first))
|
||||||
/* we can process now! */
|
|
||||||
RsIdentityDetails details;
|
|
||||||
if (mIdentities->getIdDetails(*pit, details))
|
|
||||||
{
|
|
||||||
if ((details.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED) &&(details.mFlags & RS_IDENTITY_FLAGS_PGP_KNOWN))
|
|
||||||
{
|
{
|
||||||
|
pit->second.subscription_flags |= GXS_EXTERNAL_CIRCLE_FLAGS_KEY_AVAILABLE;
|
||||||
#ifdef DEBUG_CIRCLES
|
#ifdef DEBUG_CIRCLES
|
||||||
std::cerr << " Is Known -> AllowedPeer: " << *pit << std::endl;
|
std::cerr << " Key is now available!"<< std::endl;
|
||||||
#endif
|
#endif
|
||||||
cache.addAllowedPeer(details.mPgpId, *pit);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_CIRCLES
|
|
||||||
std::cerr << " Is Unknown -> UnknownPeer: " << *pit << std::endl;
|
|
||||||
#endif
|
|
||||||
cache.mAllowedAnonPeers.insert(*pit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cerr << "p3GxsCircles::cache_load_for_token() ERROR no details: " << *pit;
|
|
||||||
std::cerr << std::endl;
|
|
||||||
// ERROR.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef DEBUG_CIRCLES
|
|
||||||
|
|
||||||
std::cerr << " Requesting UnprocessedPeer: " << *pit << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::list<PeerId> peers;
|
std::list<PeerId> peers;
|
||||||
|
|
||||||
|
if(!cache.mOriginator.isNull())
|
||||||
|
{
|
||||||
peers.push_back(cache.mOriginator) ;
|
peers.push_back(cache.mOriginator) ;
|
||||||
|
#ifdef DEBUG_CIRCLES
|
||||||
|
std::cerr << " Requesting unknown/unloaded identity: " << pit->first << " to originator " << cache.mOriginator << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << " (WW) cache entry for circle " << cache.mCircleId << " has empty originator. Asking info for GXS id " << pit->first << " to all connected friends." << std::endl;
|
||||||
|
|
||||||
mIdentities->requestKey(*pit, peers);
|
rsPeers->getOnlineList(peers) ;
|
||||||
|
}
|
||||||
|
|
||||||
/* store in to_process queue. */
|
mIdentities->requestKey(pit->first, peers);
|
||||||
cache.mUnprocessedPeers.insert(*pit);
|
|
||||||
|
|
||||||
isComplete = false;
|
|
||||||
isUnprocessedPeers = true;
|
isUnprocessedPeers = true;
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG_CIRCLES
|
||||||
|
else
|
||||||
|
std::cerr << " Key is available. Nothing to process." << std::endl;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HANDLE_SUBCIRCLES
|
#ifdef HANDLE_SUBCIRCLES
|
||||||
|
@ -1110,76 +1126,30 @@ bool p3GxsCircles::cache_load_for_token(uint32_t token)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef DEBUG_CIRCLES
|
#ifdef DEBUG_CIRCLES
|
||||||
|
else
|
||||||
std::cerr << " Loading Personal Circle" << std::endl;
|
std::cerr << " Loading Personal Circle" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// LOCAL Load.
|
// We can check for self inclusion in the circle right away, since own ids are always loaded.
|
||||||
std::set<RsPgpId> &peers = group.mLocalFriends;
|
|
||||||
std::set<RsPgpId>::const_iterator pit;
|
|
||||||
|
|
||||||
// need to trigger the searches.
|
|
||||||
for(pit = peers.begin(); pit != peers.end(); ++pit)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG_CIRCLES
|
|
||||||
std::cerr << " Local Friend: " << *pit << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cache.addLocalFriend(*pit);
|
|
||||||
}
|
|
||||||
isComplete = true;
|
|
||||||
isUnprocessedPeers = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// we can check for self inclusion in the circle right away, since own ids are always loaded.
|
|
||||||
// that allows to subscribe/unsubscribe uncomplete circles
|
// that allows to subscribe/unsubscribe uncomplete circles
|
||||||
checkCircleCacheForAutoSubscribe(cache);
|
|
||||||
|
|
||||||
if (isComplete)
|
locked_checkCircleCacheForAutoSubscribe(cache);
|
||||||
{
|
locked_checkCircleCacheForMembershipUpdate(cache);
|
||||||
|
|
||||||
|
// always store in cache even if uncomplete. But do not remove the loading items so that they can be kept in loading state.
|
||||||
|
// if(isUnprocessedPeers)
|
||||||
|
// return false ;
|
||||||
|
|
||||||
/* move straight into the cache */
|
/* move straight into the cache */
|
||||||
mCircleCache.store(id, cache);
|
mCircleCache.store(cache.mCircleId, cache);
|
||||||
mCircleCache.resize();
|
mCircleCache.resize();
|
||||||
|
|
||||||
/* remove from loading queue */
|
|
||||||
mLoadingCache.erase(it);
|
|
||||||
|
|
||||||
std::cerr << " Loading complete." << std::endl;
|
std::cerr << " Loading complete." << std::endl;
|
||||||
}
|
|
||||||
|
|
||||||
if (isUnprocessedPeers)
|
|
||||||
{
|
|
||||||
std::cerr << " Unprocessed peers. Requesting reload..." << std::endl;
|
|
||||||
|
|
||||||
/* schedule event to try reload gxsIds */
|
|
||||||
RsTickEvent::schedule_in(CIRCLE_EVENT_RELOADIDS, GXSID_LOAD_CYCLE, id.toStdString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cerr << "p3GxsCircles::cache_load_for_token() ERROR no data";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HANDLE_SUBCIRCLES
|
|
||||||
#if 0
|
|
||||||
if (!subCirclesToLoad.empty())
|
|
||||||
{
|
|
||||||
/* request load of subcircles */
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool p3GxsCircles::cache_reloadids(const RsGxsCircleId &circleId)
|
bool p3GxsCircles::cache_reloadids(const RsGxsCircleId &circleId)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_CIRCLES
|
#ifdef DEBUG_CIRCLES
|
||||||
|
@ -1202,111 +1172,58 @@ bool p3GxsCircles::cache_reloadids(const RsGxsCircleId &circleId)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
RsGxsCircleCache &cache = it->second;
|
if(locked_processLoadingCacheEntry(it->second))
|
||||||
|
|
||||||
std::list<RsGxsId> myOwnIds;
|
|
||||||
|
|
||||||
if(rsIdentity->getOwnIds(myOwnIds))
|
|
||||||
{
|
{
|
||||||
bool ownIdInCircle = false ;
|
|
||||||
|
|
||||||
for(std::list<RsGxsId>::const_iterator it(myOwnIds.begin());it!=myOwnIds.end() && !ownIdInCircle;++it)
|
|
||||||
ownIdInCircle = ownIdInCircle || cache.isAllowedPeer(*it) ;
|
|
||||||
|
|
||||||
cache.mAmIAllowed = ownIdInCircle ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* try reload Ids */
|
|
||||||
for(std::set<RsGxsId>::const_iterator pit = cache.mUnprocessedPeers.begin(); pit != cache.mUnprocessedPeers.end(); ++pit)
|
|
||||||
{
|
|
||||||
/* check cache */
|
|
||||||
if (mIdentities->haveKey(*pit))
|
|
||||||
{
|
|
||||||
/* we can process now! */
|
|
||||||
RsIdentityDetails details;
|
|
||||||
if (mIdentities->getIdDetails(*pit, details))
|
|
||||||
{
|
|
||||||
if ((details.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED) &&(details.mFlags & RS_IDENTITY_FLAGS_PGP_KNOWN))
|
|
||||||
{
|
|
||||||
cache.addAllowedPeer(details.mPgpId, *pit);
|
|
||||||
|
|
||||||
#ifdef DEBUG_CIRCLES
|
|
||||||
std::cerr << "p3GxsCircles::cache_reloadids() AllowedPeer: ";
|
|
||||||
std::cerr << *pit;
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif // DEBUG_CIRCLES
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cache.mAllowedAnonPeers.insert(*pit);
|
|
||||||
|
|
||||||
#ifdef DEBUG_CIRCLES
|
|
||||||
std::cerr << "p3GxsCircles::cache_reloadids() UnknownPeer: ";
|
|
||||||
std::cerr << *pit;
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif // DEBUG_CIRCLES
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// ERROR.
|
|
||||||
std::cerr << "p3GxsCircles::cache_reloadids() ERROR ";
|
|
||||||
std::cerr << " Should haveKey for Id: " << *pit;
|
|
||||||
std::cerr << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// UNKNOWN ID.
|
|
||||||
std::cerr << "p3GxsCircles::cache_reloadids() UNKNOWN Id: ";
|
|
||||||
std::cerr << *pit;
|
|
||||||
std::cerr << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear unprocessed List.
|
|
||||||
cache.mUnprocessedPeers.clear();
|
|
||||||
|
|
||||||
// If sub-circles are complete too.
|
|
||||||
#ifdef SUBSCIRCLES
|
|
||||||
if (cache.mUnprocessedCircles.empty())
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
#ifdef DEBUG_CIRCLES
|
|
||||||
std::cerr << "p3GxsCircles::cache_reloadids() Adding to cache Id: ";
|
|
||||||
std::cerr << circleId;
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif // DEBUG_CIRCLES
|
|
||||||
|
|
||||||
checkCircleCacheForAutoSubscribe(cache);
|
|
||||||
|
|
||||||
// Push to Cache.
|
|
||||||
mCircleCache.store(circleId, cache);
|
|
||||||
mCircleCache.resize();
|
|
||||||
|
|
||||||
/* remove from loading queue */
|
/* remove from loading queue */
|
||||||
mLoadingCache.erase(it);
|
mLoadingCache.erase(it);
|
||||||
#ifdef SUBSCIRCLES
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cerr << "p3GxsCircles::cache_reloadids() WARNING Incomplete Cache Loading: ";
|
std::cerr << " Unprocessed peers. Requesting reload for circle " << circleId << std::endl;
|
||||||
std::cerr << circleId;
|
|
||||||
std::cerr << std::endl;
|
/* schedule event to try reload gxsIds */
|
||||||
|
RsTickEvent::schedule_in(CIRCLE_EVENT_RELOADIDS, GXSID_LOAD_CYCLE, circleId.toStdString());
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool p3GxsCircles::checkCircleCacheForMembershipUpdate()
|
||||||
|
{
|
||||||
|
#warning TODO. Should go over existing cache entries and update/process the membership requests
|
||||||
|
std::cerr << __PRETTY_FUNCTION__ << ": not implemented!" << std::endl;
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool p3GxsCircles::locked_checkCircleCacheForMembershipUpdate(RsGxsCircleCache& cache)
|
||||||
|
{
|
||||||
|
time_t now = time(NULL) ;
|
||||||
|
|
||||||
|
if(cache.mLastUpdatedMembershipTS + GXS_CIRCLE_DELAY_TO_FORCE_MEMBERSHIP_UPDATE < now)
|
||||||
|
{
|
||||||
|
std::cerr << "Cache entry for circle " << cache.mCircleId << " needs a swab over membership requests. Re-scheduling it." << std::endl;
|
||||||
|
|
||||||
|
// this should be called regularly
|
||||||
|
|
||||||
|
uint32_t token ;
|
||||||
|
RsTokReqOptions opts;
|
||||||
|
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
|
||||||
|
std::list<RsGxsGroupId> grpIds ;
|
||||||
|
|
||||||
|
grpIds.push_back(RsGxsGroupId(cache.mCircleId)) ;
|
||||||
|
|
||||||
|
RsGenExchange::getTokenService()->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, grpIds);
|
||||||
|
GxsTokenQueue::queueRequest(token, CIRCLEREQ_MESSAGE_DATA);
|
||||||
|
}
|
||||||
|
return true ;
|
||||||
|
}
|
||||||
|
|
||||||
/* We need to AutoSubscribe if the Circle is relevent to us */
|
/* We need to AutoSubscribe if the Circle is relevent to us */
|
||||||
|
|
||||||
bool p3GxsCircles::checkCircleCacheForAutoSubscribe(RsGxsCircleCache &cache)
|
bool p3GxsCircles::locked_checkCircleCacheForAutoSubscribe(RsGxsCircleCache &cache)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_CIRCLES
|
#ifdef DEBUG_CIRCLES
|
||||||
std::cerr << "p3GxsCircles::checkCircleCacheForAutoSubscribe() : "<< cache.mCircleId << std::endl;
|
std::cerr << "p3GxsCircles::locked_checkCircleCacheForAutoSubscribe() : "<< cache.mCircleId << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* if processed already - ignore */
|
/* if processed already - ignore */
|
||||||
|
@ -1331,11 +1248,34 @@ bool p3GxsCircles::checkCircleCacheForAutoSubscribe(RsGxsCircleCache &cache)
|
||||||
|
|
||||||
/* if we appear in the group - then autosubscribe, and mark as processed */
|
/* if we appear in the group - then autosubscribe, and mark as processed */
|
||||||
|
|
||||||
const RsPgpId& ownPgpId = mPgpUtils->getPGPOwnId();
|
// const RsPgpId& ownPgpId = mPgpUtils->getPGPOwnId();
|
||||||
|
|
||||||
bool am_I_allowed = cache.mAmIAllowed || (cache.mAllowedSignedPeers.find(ownPgpId) != cache.mAllowedSignedPeers.end()) ;
|
std::list<RsGxsId> myOwnIds;
|
||||||
|
|
||||||
if(am_I_allowed)
|
if(!rsIdentity->getOwnIds(myOwnIds))
|
||||||
|
{
|
||||||
|
std::cerr << " own ids not loaded yet." << std::endl;
|
||||||
|
|
||||||
|
/* schedule event to try reload gxsIds */
|
||||||
|
RsTickEvent::schedule_in(CIRCLE_EVENT_RELOADIDS, GXSID_LOAD_CYCLE, cache.mCircleId.toStdString());
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool in_admin_list = false ;
|
||||||
|
|
||||||
|
for(std::list<RsGxsId>::const_iterator it(myOwnIds.begin());it!=myOwnIds.end() && !in_admin_list;++it)
|
||||||
|
{
|
||||||
|
std::map<RsGxsId,RsGxsCircleMembershipStatus>::const_iterator it2 = cache.mMembershipStatus.find(*it) ;
|
||||||
|
|
||||||
|
if(it2 != cache.mMembershipStatus.end())
|
||||||
|
in_admin_list = in_admin_list || (it2->second.subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_CIRCLES
|
||||||
|
std::cerr << " own ID in circle: " << in_admin_list << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(in_admin_list)
|
||||||
{
|
{
|
||||||
uint32_t token, token2;
|
uint32_t token, token2;
|
||||||
|
|
||||||
|
@ -1358,7 +1298,7 @@ bool p3GxsCircles::checkCircleCacheForAutoSubscribe(RsGxsCircleCache &cache)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (cache.mUnprocessedPeers.empty())
|
else
|
||||||
{
|
{
|
||||||
/* we know all the peers - we are not part - we can flag as PROCESSED. */
|
/* we know all the peers - we are not part - we can flag as PROCESSED. */
|
||||||
uint32_t token,token2;
|
uint32_t token,token2;
|
||||||
|
@ -1380,15 +1320,6 @@ bool p3GxsCircles::checkCircleCacheForAutoSubscribe(RsGxsCircleCache &cache)
|
||||||
|
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef DEBUG_CIRCLES
|
|
||||||
std::cerr << " Leaving Unprocessed" << std::endl;
|
|
||||||
#endif
|
|
||||||
// Don't clear UNPROCESSED - as we might not know all the peers.
|
|
||||||
// TODO - work out when we flag as PROCESSED.
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void p3GxsCircles::addCircleIdToList(const RsGxsCircleId &circleId, uint32_t circleType)
|
void p3GxsCircles::addCircleIdToList(const RsGxsCircleId &circleId, uint32_t circleType)
|
||||||
|
@ -1810,6 +1741,10 @@ void p3GxsCircles::handleResponse(uint32_t token, uint32_t req_type)
|
||||||
load_CircleIdList(token);
|
load_CircleIdList(token);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CIRCLEREQ_MESSAGE_DATA:
|
||||||
|
processMembershipRequests(token);
|
||||||
|
break;
|
||||||
|
|
||||||
case CIRCLEREQ_CACHELOAD:
|
case CIRCLEREQ_CACHELOAD:
|
||||||
cache_load_for_token(token);
|
cache_load_for_token(token);
|
||||||
break;
|
break;
|
||||||
|
@ -1879,5 +1814,230 @@ void p3GxsCircles::handle_event(uint32_t event_type, const std::string &elabel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Circle membership is requested/denied by posting a message into the cicle group, according to the following rules:
|
||||||
|
//
|
||||||
|
// - a subscription request is a RsItem (which serialises into a radix64 message, that is further signed by the group message publishing system)
|
||||||
|
// The item contains:
|
||||||
|
// * subscribe order (yes/no), boolean
|
||||||
|
// * circle ID (this is important, otherwise people can copy subscribe messages from one circle to another)
|
||||||
|
// * subscribe date
|
||||||
|
// * subscribe timeout (how long is the message kept. When timed out, the message is removed and subscription cancelled)
|
||||||
|
//
|
||||||
|
// - subscribe messages follow the following rules, which are enforced by a timer-based method:
|
||||||
|
// * subscription requests from a given user are always replaced by the last subscription request
|
||||||
|
// * a complete list of who's subscribed to a given group is kept, saved, and regularly updated when new subscribe messages are received, or when admin list is changed.
|
||||||
|
// * getGroupDetails reads this list in order to respond who's subscribed to a group. The list of
|
||||||
|
//
|
||||||
|
// - compatibility with self-restricted circles:
|
||||||
|
// * subscription should be based on admin list, so that non subscribed peers still receive the invitation
|
||||||
|
//
|
||||||
|
// - two possible subscription models for circle member list (Restricted forums only propagate to members):
|
||||||
|
// 1 - list of admin who have not opposed subscription
|
||||||
|
// - solves propagation issue. Only admin see data. They can however unsubscribe using a negative req. Admin needs to remove them.
|
||||||
|
// - bad for security. Admin can refuse to remove them => back to square one
|
||||||
|
// 2 - list of admin who have also requested membership
|
||||||
|
// - propagation is ok. On restricted circle, the circle msgs/group should be sent to admin list, instead of member list.
|
||||||
|
// - solves membership issue since people need to actively be in the group.
|
||||||
|
// => choose 2
|
||||||
|
// - forum group : encrypted for Member list
|
||||||
|
// - circle group : clear / encrypted for admin list (for self-restricted)
|
||||||
|
// We decide between the two by comparing the group we're sending and the circle id it is restricted to.
|
||||||
|
//
|
||||||
|
// - Use cases
|
||||||
|
// * user sees group (not self restricted) and requests to subscribe => RS subscribes the group and the user can propagate the response
|
||||||
|
// * user is invited to self-restricted circle. He will see it and can subscribe, so he will be in admin list and receive e.g. forum posts.
|
||||||
|
// *
|
||||||
|
//
|
||||||
|
// - Threat model
|
||||||
|
// * a malicious user forges a new subscription request: NP-hard as it needs to break the RSA key of the GXS id.
|
||||||
|
// * a malicious corrupts a subscription request: NP-hard. Messages are signed.
|
||||||
|
// * a malicious user copies an old subscription of someone else and inserts it in the system.
|
||||||
|
// => not possible. Either this existing old susbscription already exists, or it has been replaced by a more recent one, which
|
||||||
|
// will always replace the old one because of the date.
|
||||||
|
// * a malicious user removes someone's subscription messages. This is possible, but the mesh nature of the network will allow the message to propagate anyway.
|
||||||
|
// * a malicious user creates a circle with an incriminating name/content and adds everyone in it
|
||||||
|
// => people can oppose their membership in the circle using a msg
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// - the table below summarizes the various choices: forum and circle propagation when restricted to a circle, and group subscribe to the circle
|
||||||
|
//
|
||||||
|
// +------------------------------+-----------------------------+
|
||||||
|
// | User in admin list | User not in admin list |
|
||||||
|
// +-------------+------------------------------+-----------------------------+
|
||||||
|
// | User request| Forum Grp/Msg: YES | Forum Grp/Msg: NO |
|
||||||
|
// | Subscription| Circle Grp/Msg: YES/YES | Circle Grp/Msg: YES/NO |
|
||||||
|
// | | Grp Subscribed: YES | Grp Subscribed: YES |
|
||||||
|
// +-------------+------------------------------+-----------------------------+
|
||||||
|
// | No request | Forum Grp/Msg: NO | Forum Grp/Msg: NO |
|
||||||
|
// | Subscription| Circle Grp/Msg: YES/YES | Circle Grp/Msg: YES/NO |
|
||||||
|
// | | Grp Subscribed: NO | Grp Subscribed: NO |
|
||||||
|
// +-------------+------------------------------+-----------------------------+
|
||||||
|
|
||||||
|
bool p3GxsCircles::pushCircleMembershipRequest(const RsGxsId& own_gxsid,const RsGxsCircleId& circle_id,uint32_t request_type)
|
||||||
|
{
|
||||||
|
std::cerr << "Circle membership request: own_gxsid = " << own_gxsid << ", circle=" << circle_id << ", req type=" << request_type << std::endl;
|
||||||
|
|
||||||
|
// check for some consistency
|
||||||
|
|
||||||
|
if(request_type != RsGxsCircleSubscriptionRequestItem::SUBSCRIPTION_REQUEST_SUBSCRIBE && request_type != RsGxsCircleSubscriptionRequestItem::SUBSCRIPTION_REQUEST_UNSUBSCRIBE)
|
||||||
|
return false ;
|
||||||
|
|
||||||
|
std::list<RsGxsId> own_ids ;
|
||||||
|
if(!rsIdentity->getOwnIds(own_ids))
|
||||||
|
return false ;
|
||||||
|
|
||||||
|
bool found = false ;
|
||||||
|
for(std::list<RsGxsId>::const_iterator it(own_ids.begin());it!=own_ids.end() && !found;++it)
|
||||||
|
found = ( (*it) == own_gxsid) ;
|
||||||
|
|
||||||
|
if(!found)
|
||||||
|
return false ;
|
||||||
|
|
||||||
|
// Create a subscribe item
|
||||||
|
|
||||||
|
RsGxsCircleSubscriptionRequestItem *s = new RsGxsCircleSubscriptionRequestItem ;
|
||||||
|
|
||||||
|
s->time_stamp = time(NULL) ;
|
||||||
|
s->time_out = 0 ; // means never
|
||||||
|
s->subscription_type = request_type ;
|
||||||
|
|
||||||
|
RsTemporaryMemory tmpmem(circle_id.serial_size() + own_gxsid.serial_size()) ;
|
||||||
|
|
||||||
|
uint32_t off = 0 ;
|
||||||
|
circle_id.serialise(tmpmem,tmpmem.size(),off) ;
|
||||||
|
own_gxsid.serialise(tmpmem,tmpmem.size(),off) ;
|
||||||
|
|
||||||
|
s->meta.mGroupId = RsGxsGroupId(circle_id) ;
|
||||||
|
s->meta.mMsgId.clear();
|
||||||
|
s->meta.mThreadId = RsDirUtil::sha1sum(tmpmem,tmpmem.size()); // make the ID from the hash of the cirle ID and the author ID
|
||||||
|
s->meta.mAuthorId = own_gxsid;
|
||||||
|
|
||||||
|
// msgItem->meta.mParentId = ; // leave these blank
|
||||||
|
// msgItem->meta.mOrigMsgId= ;
|
||||||
|
|
||||||
|
std::cerr << "p3GxsCircles::publishSubscribeRequest()" << std::endl;
|
||||||
|
std::cerr << " GroupId : " << circle_id << std::endl;
|
||||||
|
std::cerr << " AuthorId : " << s->meta.mAuthorId << std::endl;
|
||||||
|
std::cerr << " ThreadId : " << s->meta.mThreadId << std::endl;
|
||||||
|
|
||||||
|
uint32_t token ;
|
||||||
|
RsGenExchange::publishMsg(token, s);
|
||||||
|
|
||||||
|
// update the cache.
|
||||||
|
force_cache_reload(circle_id);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool p3GxsCircles::requestCircleMembership(const RsGxsId& own_gxsid,const RsGxsCircleId& circle_id)
|
||||||
|
{
|
||||||
|
return pushCircleMembershipRequest(own_gxsid,circle_id,RsGxsCircleSubscriptionRequestItem::SUBSCRIPTION_REQUEST_SUBSCRIBE) ;
|
||||||
|
}
|
||||||
|
bool p3GxsCircles::cancelCircleMembership(const RsGxsId& own_gxsid,const RsGxsCircleId& circle_id)
|
||||||
|
{
|
||||||
|
return pushCircleMembershipRequest(own_gxsid,circle_id,RsGxsCircleSubscriptionRequestItem::SUBSCRIPTION_REQUEST_UNSUBSCRIBE) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool p3GxsCircles::processMembershipRequests(uint32_t token)
|
||||||
|
{
|
||||||
|
// Go through membership request messages and process them according to the following rule:
|
||||||
|
// * for each ID only keep the latest membership request. Delete the older ones.
|
||||||
|
// * for each circle, keep a list of IDs sorted into membership categories (e.g. keep updated flags for each IDs)
|
||||||
|
// Because msg loading is async-ed, the job in split in two methods: one calls the loading, the other one handles the loaded data.
|
||||||
|
|
||||||
|
#ifdef DEBUG_CIRCLES
|
||||||
|
std::cerr << "Processing circle membership requests." << std::endl;
|
||||||
|
#endif
|
||||||
|
GxsMsgDataMap msgItems ;
|
||||||
|
|
||||||
|
if(!RsGenExchange::getMsgData(token, msgItems))
|
||||||
|
{
|
||||||
|
std::cerr << "(EE) Cannot get msg data for circle. Something's weird." << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GxsMsgReq messages_to_delete ;
|
||||||
|
|
||||||
|
for(GxsMsgDataMap::const_iterator it(msgItems.begin());it!=msgItems.end();++it)
|
||||||
|
{
|
||||||
|
RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/
|
||||||
|
std::cerr << " Circle ID: " << it->first << std::endl;
|
||||||
|
|
||||||
|
RsGxsCircleId cid ( it->first );
|
||||||
|
|
||||||
|
if (!mCircleCache.is_cached(cid))
|
||||||
|
{
|
||||||
|
std::cerr << " (EE) Circle is not in cache!" << std::endl;
|
||||||
|
continue ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the circle ID in cache and process the list of messages to keep the latest order in time.
|
||||||
|
|
||||||
|
RsGxsCircleCache& data = mCircleCache.ref(cid);
|
||||||
|
std::cerr << " Circle found in cache!" << std::endl;
|
||||||
|
std::cerr << " Retrieving messages..." << std::endl;
|
||||||
|
|
||||||
|
for(uint32_t i=0;i<it->second.size();++i)
|
||||||
|
{
|
||||||
|
std::cerr << " Group ID: " << it->second[i]->meta.mGroupId << ", Message ID: " << it->second[i]->meta.mMsgId << ": " ;
|
||||||
|
|
||||||
|
RsGxsCircleSubscriptionRequestItem *item = dynamic_cast<RsGxsCircleSubscriptionRequestItem*>(it->second[i]) ;
|
||||||
|
|
||||||
|
if(item == NULL)
|
||||||
|
{
|
||||||
|
std::cerr << " (EE) item is not a RsGxsCircleSubscriptionRequestItem. Weird." << std::endl;
|
||||||
|
continue ;
|
||||||
|
}
|
||||||
|
|
||||||
|
RsGxsCircleMembershipStatus& info(data.mMembershipStatus[item->meta.mAuthorId]) ;
|
||||||
|
|
||||||
|
std::cerr << " is from id " << item->meta.mAuthorId << " " << time(NULL) - item->time_stamp << " seconds ago, " ;
|
||||||
|
|
||||||
|
if(info.last_subscription_TS < item->time_stamp)
|
||||||
|
{
|
||||||
|
info.last_subscription_TS = item->time_stamp ;
|
||||||
|
|
||||||
|
if(item->subscription_type == RsGxsCircleSubscriptionRequestItem::SUBSCRIPTION_REQUEST_SUBSCRIBE)
|
||||||
|
info.subscription_flags |= GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED;
|
||||||
|
else if(item->subscription_type == RsGxsCircleSubscriptionRequestItem::SUBSCRIPTION_REQUEST_UNSUBSCRIBE)
|
||||||
|
info.subscription_flags &= ~GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED;
|
||||||
|
else
|
||||||
|
std::cerr << " (EE) unknown subscription order type: " << item->subscription_type ;
|
||||||
|
|
||||||
|
std::cerr << " UPDATING" << std::endl;
|
||||||
|
}
|
||||||
|
else if(info.last_subscription_TS > item->time_stamp)
|
||||||
|
{
|
||||||
|
std::cerr << " Older than last known (" << time(NULL)-info.last_subscription_TS << " seconds ago): deleting." << std::endl;
|
||||||
|
messages_to_delete[RsGxsGroupId(cid)].push_back(it->second[i]->meta.mMsgId) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data.mLastUpdatedMembershipTS = time(NULL) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/
|
||||||
|
uint32_t token2;
|
||||||
|
RsGenExchange::deleteMsgs(token2,messages_to_delete);
|
||||||
|
|
||||||
|
return true ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -124,6 +124,15 @@
|
||||||
/* Permissions is part of GroupMetaData
|
/* Permissions is part of GroupMetaData
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
class RsGxsCircleMembershipStatus
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RsGxsCircleMembershipStatus() : last_subscription_TS(0), subscription_flags(0) {}
|
||||||
|
|
||||||
|
time_t last_subscription_TS ;
|
||||||
|
uint32_t subscription_flags ; // combination of GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST and GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED
|
||||||
|
};
|
||||||
|
|
||||||
class RsGxsCircleCache
|
class RsGxsCircleCache
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -134,8 +143,8 @@ class RsGxsCircleCache
|
||||||
|
|
||||||
bool getAllowedPeersList(std::list<RsPgpId> &friendlist) const;
|
bool getAllowedPeersList(std::list<RsPgpId> &friendlist) const;
|
||||||
bool isAllowedPeer(const RsPgpId &id) const;
|
bool isAllowedPeer(const RsPgpId &id) const;
|
||||||
bool isAllowedPeer(const RsGxsId &id) const;
|
bool isAllowedPeer(const RsGxsId &id, const RsGxsGroupId &destination_group) const;
|
||||||
bool addAllowedPeer(const RsPgpId &pgpid, const RsGxsId &gxsId);
|
bool addAllowedPeer(const RsPgpId &pgpid);
|
||||||
bool addLocalFriend(const RsPgpId &pgpid);
|
bool addLocalFriend(const RsPgpId &pgpid);
|
||||||
|
|
||||||
RsGxsCircleId mCircleId;
|
RsGxsCircleId mCircleId;
|
||||||
|
@ -143,7 +152,6 @@ class RsGxsCircleCache
|
||||||
|
|
||||||
uint32_t mCircleType;
|
uint32_t mCircleType;
|
||||||
bool mIsExternal;
|
bool mIsExternal;
|
||||||
bool mAmIAllowed ;
|
|
||||||
|
|
||||||
uint32_t mGroupStatus;
|
uint32_t mGroupStatus;
|
||||||
uint32_t mGroupSubscribeFlags;
|
uint32_t mGroupSubscribeFlags;
|
||||||
|
@ -153,10 +161,11 @@ class RsGxsCircleCache
|
||||||
std::set<RsGxsCircleId> mUnprocessedCircles;
|
std::set<RsGxsCircleId> mUnprocessedCircles;
|
||||||
std::set<RsGxsCircleId> mProcessedCircles;
|
std::set<RsGxsCircleId> mProcessedCircles;
|
||||||
#endif
|
#endif
|
||||||
std::set<RsGxsId> mUnprocessedPeers;
|
std::map<RsGxsId,RsGxsCircleMembershipStatus> mMembershipStatus;
|
||||||
|
time_t mLastUpdatedMembershipTS ; // last time the subscribe messages have been requested. Should be reset when new messages arrive.
|
||||||
|
|
||||||
std::set<RsGxsId> mAllowedAnonPeers;
|
std::set<RsGxsId> mAllowedGxsIds; // IDs that are allowed in the circle and have requested membership. This is the official members list.
|
||||||
std::map<RsPgpId, std::set<RsGxsId> > mAllowedSignedPeers;
|
std::set<RsPgpId> mAllowedNodes;
|
||||||
|
|
||||||
RsPeerId mOriginator ; // peer who sent the data, in case we need to ask for ids
|
RsPeerId mOriginator ; // peer who sent the data, in case we need to ask for ids
|
||||||
};
|
};
|
||||||
|
@ -164,12 +173,10 @@ class RsGxsCircleCache
|
||||||
|
|
||||||
class PgpAuxUtils;
|
class PgpAuxUtils;
|
||||||
|
|
||||||
class p3GxsCircles: public RsGxsCircleExchange, public RsGxsCircles,
|
class p3GxsCircles: public RsGxsCircleExchange, public RsGxsCircles, public GxsTokenQueue, public RsTickEvent
|
||||||
public GxsTokenQueue, public RsTickEvent
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
p3GxsCircles(RsGeneralDataService* gds, RsNetworkExchangeService* nes,
|
p3GxsCircles(RsGeneralDataService* gds, RsNetworkExchangeService* nes, p3IdService *identities, PgpAuxUtils *pgpUtils);
|
||||||
p3IdService *identities, PgpAuxUtils *pgpUtils);
|
|
||||||
|
|
||||||
virtual RsServiceInfo getServiceInfo();
|
virtual RsServiceInfo getServiceInfo();
|
||||||
|
|
||||||
|
@ -184,9 +191,10 @@ virtual RsServiceInfo getServiceInfo();
|
||||||
|
|
||||||
virtual int canSend(const RsGxsCircleId &circleId, const RsPgpId &id, bool &should_encrypt);
|
virtual int canSend(const RsGxsCircleId &circleId, const RsPgpId &id, bool &should_encrypt);
|
||||||
virtual int canReceive(const RsGxsCircleId &circleId, const RsPgpId &id);
|
virtual int canReceive(const RsGxsCircleId &circleId, const RsPgpId &id);
|
||||||
|
|
||||||
virtual bool recipients(const RsGxsCircleId &circleId, std::list<RsPgpId> &friendlist) ;
|
virtual bool recipients(const RsGxsCircleId &circleId, std::list<RsPgpId> &friendlist) ;
|
||||||
virtual bool recipients(const RsGxsCircleId &circleId, std::list<RsGxsId> &gxs_ids) ;
|
virtual bool recipients(const RsGxsCircleId &circleId, const RsGxsGroupId& dest_group, std::list<RsGxsId> &gxs_ids) ;
|
||||||
virtual bool isRecipient(const RsGxsCircleId &circleId, const RsGxsId& id) ;
|
virtual bool isRecipient(const RsGxsCircleId &circleId, const RsGxsGroupId& destination_group, const RsGxsId& id) ;
|
||||||
|
|
||||||
|
|
||||||
virtual bool getGroupData(const uint32_t &token, std::vector<RsGxsCircleGroup> &groups);
|
virtual bool getGroupData(const uint32_t &token, std::vector<RsGxsCircleGroup> &groups);
|
||||||
|
@ -194,6 +202,11 @@ virtual RsServiceInfo getServiceInfo();
|
||||||
virtual void updateGroup(uint32_t &token, RsGxsCircleGroup &group);
|
virtual void updateGroup(uint32_t &token, RsGxsCircleGroup &group);
|
||||||
|
|
||||||
|
|
||||||
|
/* membership management for external circles */
|
||||||
|
|
||||||
|
virtual bool requestCircleMembership(const RsGxsId &own_gxsid, const RsGxsCircleId& circle_id) ;
|
||||||
|
virtual bool cancelCircleMembership(const RsGxsId &own_gxsid, const RsGxsCircleId& circle_id) ;
|
||||||
|
|
||||||
/**********************************************/
|
/**********************************************/
|
||||||
|
|
||||||
// needed for background processing.
|
// needed for background processing.
|
||||||
|
@ -201,6 +214,7 @@ virtual RsServiceInfo getServiceInfo();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
bool pushCircleMembershipRequest(const RsGxsId& own_gxsid,const RsGxsCircleId& circle_id,uint32_t request_type) ;
|
||||||
static uint32_t circleAuthenPolicy();
|
static uint32_t circleAuthenPolicy();
|
||||||
|
|
||||||
/** Notifications **/
|
/** Notifications **/
|
||||||
|
@ -220,6 +234,7 @@ virtual RsServiceInfo getServiceInfo();
|
||||||
// Load data.
|
// Load data.
|
||||||
bool request_CircleIdList();
|
bool request_CircleIdList();
|
||||||
bool load_CircleIdList(uint32_t token);
|
bool load_CircleIdList(uint32_t token);
|
||||||
|
bool processMembershipRequests(uint32_t token);
|
||||||
|
|
||||||
// Need some crazy arsed cache to store the circle info.
|
// Need some crazy arsed cache to store the circle info.
|
||||||
// so we don't have to keep loading groups.
|
// so we don't have to keep loading groups.
|
||||||
|
@ -232,8 +247,11 @@ virtual RsServiceInfo getServiceInfo();
|
||||||
bool cache_load_for_token(uint32_t token);
|
bool cache_load_for_token(uint32_t token);
|
||||||
bool cache_reloadids(const RsGxsCircleId &circleId);
|
bool cache_reloadids(const RsGxsCircleId &circleId);
|
||||||
|
|
||||||
bool checkCircleCacheForAutoSubscribe(RsGxsCircleCache &cache);
|
bool checkCircleCacheForMembershipUpdate();
|
||||||
|
|
||||||
|
bool locked_checkCircleCacheForAutoSubscribe(RsGxsCircleCache &cache);
|
||||||
|
bool locked_processLoadingCacheEntry(RsGxsCircleCache &cache);
|
||||||
|
bool locked_checkCircleCacheForMembershipUpdate(RsGxsCircleCache &cache);
|
||||||
|
|
||||||
p3IdService *mIdentities; // Needed for constructing Circle Info,
|
p3IdService *mIdentities; // Needed for constructing Circle Info,
|
||||||
PgpAuxUtils *mPgpUtils;
|
PgpAuxUtils *mPgpUtils;
|
||||||
|
@ -270,12 +288,11 @@ virtual RsServiceInfo getServiceInfo();
|
||||||
void checkDummyIdData();
|
void checkDummyIdData();
|
||||||
void generateDummyCircle();
|
void generateDummyCircle();
|
||||||
|
|
||||||
|
time_t mLastCacheMembershipUpdateTS ;
|
||||||
|
|
||||||
uint32_t mDummyIdToken;
|
uint32_t mDummyIdToken;
|
||||||
std::list<RsGxsId> mDummyPgpLinkedIds;
|
std::list<RsGxsId> mDummyPgpLinkedIds;
|
||||||
std::list<RsGxsId> mDummyOwnIds;
|
std::list<RsGxsId> mDummyOwnIds;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // P3_CIRCLES_SERVICE_HEADER
|
#endif // P3_CIRCLES_SERVICE_HEADER
|
||||||
|
|
|
@ -101,7 +101,7 @@ again:
|
||||||
/****************
|
/****************
|
||||||
* create a radix64 encoded string.
|
* create a radix64 encoded string.
|
||||||
*/
|
*/
|
||||||
static void encode(const char *data,int len,std::string& out_string)
|
static void encode(const unsigned char *data,int len,std::string& out_string)
|
||||||
{
|
{
|
||||||
char *buffer, *p;
|
char *buffer, *p;
|
||||||
|
|
||||||
|
|
|
@ -486,7 +486,9 @@ bool RsRecogn::itemToRadix64(RsItem *item, std::string &radstr)
|
||||||
|
|
||||||
/* write out the item for signing */
|
/* write out the item for signing */
|
||||||
uint32_t len = serialiser.size(item);
|
uint32_t len = serialiser.size(item);
|
||||||
char *buf = new char[len];
|
|
||||||
|
RsTemporaryMemory buf(len) ;
|
||||||
|
|
||||||
if (!serialiser.serialise(item, buf, &len))
|
if (!serialiser.serialise(item, buf, &len))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -609,7 +611,7 @@ bool RsRecogn::createTagRequest(const RsTlvSecurityKey &key, const RsGxsId &id,
|
||||||
/* write out the item for signing */
|
/* write out the item for signing */
|
||||||
RsGxsRecognSerialiser serialiser;
|
RsGxsRecognSerialiser serialiser;
|
||||||
uint32_t len = serialiser.size(item);
|
uint32_t len = serialiser.size(item);
|
||||||
char *buf = new char[len];
|
RsTemporaryMemory buf(len) ;
|
||||||
bool serOk = serialiser.serialise(item, buf, &len);
|
bool serOk = serialiser.serialise(item, buf, &len);
|
||||||
|
|
||||||
if (serOk)
|
if (serOk)
|
||||||
|
@ -617,8 +619,6 @@ bool RsRecogn::createTagRequest(const RsTlvSecurityKey &key, const RsGxsId &id,
|
||||||
Radix64::encode(buf, len, tag);
|
Radix64::encode(buf, len, tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete []buf;
|
|
||||||
|
|
||||||
if (!serOk)
|
if (!serOk)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_RECOGN
|
#ifdef DEBUG_RECOGN
|
||||||
|
|
|
@ -315,7 +315,7 @@ void mark_circle_item(QTreeWidgetItem *item, const std::set<RsPgpId> &names)
|
||||||
std::set<RsPgpId>::iterator it;
|
std::set<RsPgpId>::iterator it;
|
||||||
for(it = names.begin(); it != names.end(); ++it)
|
for(it = names.begin(); it != names.end(); ++it)
|
||||||
{
|
{
|
||||||
if (details.mAllowedSignedPeers.end() != details.mAllowedSignedPeers.find(*it))
|
if (details.mAllowedNodes.end() != details.mAllowedNodes.find(*it))
|
||||||
{
|
{
|
||||||
set_item_background(item, GREEN_BACKGROUND);
|
set_item_background(item, GREEN_BACKGROUND);
|
||||||
std::cerr << "CirclesDialog mark_circle_item: found match: " << id;
|
std::cerr << "CirclesDialog mark_circle_item: found match: " << id;
|
||||||
|
@ -387,15 +387,7 @@ void CirclesDialog::circle_selected()
|
||||||
if (rsGxsCircles->getCircleDetails(id, details))
|
if (rsGxsCircles->getCircleDetails(id, details))
|
||||||
{
|
{
|
||||||
/* now mark all the members */
|
/* now mark all the members */
|
||||||
std::set<RsPgpId> members;
|
mark_matching_tree(ui.treeWidget_friends, details.mAllowedNodes, CIRCLEGROUP_FRIEND_COL_ID, GREEN_BACKGROUND);
|
||||||
for( std::map<RsPgpId, std::set<RsGxsId> >::iterator it = details.mAllowedSignedPeers.begin(); it != details.mAllowedSignedPeers.end(); ++it)
|
|
||||||
{
|
|
||||||
members.insert(it->first);
|
|
||||||
std::cerr << "Circle member: " << it->first;
|
|
||||||
std::cerr << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
mark_matching_tree(ui.treeWidget_friends, members, CIRCLEGROUP_FRIEND_COL_ID, GREEN_BACKGROUND);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -300,8 +300,8 @@ void CreateCircleDialog::addMember(const QString& keyId, const QString& idtype,
|
||||||
void CreateCircleDialog::addCircle(const RsGxsCircleDetails &cirDetails)
|
void CreateCircleDialog::addCircle(const RsGxsCircleDetails &cirDetails)
|
||||||
{
|
{
|
||||||
typedef std::set<RsGxsId>::iterator itUnknownPeers;
|
typedef std::set<RsGxsId>::iterator itUnknownPeers;
|
||||||
for (itUnknownPeers it = cirDetails.mAllowedAnonPeers.begin()
|
for (itUnknownPeers it = cirDetails.mAllowedGxsIds.begin()
|
||||||
; it != cirDetails.mAllowedAnonPeers.end()
|
; it != cirDetails.mAllowedGxsIds.end()
|
||||||
; ++it) {
|
; ++it) {
|
||||||
RsGxsId gxs_id = *it;
|
RsGxsId gxs_id = *it;
|
||||||
RsIdentityDetails gxs_details ;
|
RsIdentityDetails gxs_details ;
|
||||||
|
@ -316,10 +316,10 @@ void CreateCircleDialog::addCircle(const RsGxsCircleDetails &cirDetails)
|
||||||
}//if(!gxs_id.isNull() && rsIdentity->getIdDetails(gxs_id,gxs_details))
|
}//if(!gxs_id.isNull() && rsIdentity->getIdDetails(gxs_id,gxs_details))
|
||||||
}//for (itUnknownPeers it = cirDetails.mUnknownPeers.begin()
|
}//for (itUnknownPeers it = cirDetails.mUnknownPeers.begin()
|
||||||
|
|
||||||
typedef std::map<RsPgpId, std::set<RsGxsId> >::const_iterator itAllowedPeers;
|
typedef std::set<RsPgpId>::const_iterator itAllowedPeers;
|
||||||
for (itAllowedPeers it = cirDetails.mAllowedSignedPeers.begin() ; it != cirDetails.mAllowedSignedPeers.end() ; ++it )
|
for (itAllowedPeers it = cirDetails.mAllowedNodes.begin() ; it != cirDetails.mAllowedNodes.end() ; ++it )
|
||||||
{
|
{
|
||||||
RsPgpId gpg_id = it->first;
|
RsPgpId gpg_id = *it;
|
||||||
RsPeerDetails details ;
|
RsPeerDetails details ;
|
||||||
if(!gpg_id.isNull() && rsPeers->getGPGDetails(gpg_id,details)) {
|
if(!gpg_id.isNull() && rsPeers->getGPGDetails(gpg_id,details)) {
|
||||||
|
|
||||||
|
|
|
@ -14,16 +14,7 @@
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
<property name="leftMargin">
|
<property name="margin">
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
|
@ -53,7 +44,7 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBox_2">
|
<widget class="QGroupBox" name="groupBox_2">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Circle Members</string>
|
<string>Invited Members</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
|
@ -155,16 +146,7 @@
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="leftMargin">
|
<property name="margin">
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
|
@ -341,16 +323,7 @@
|
||||||
<enum>QFrame::Raised</enum>
|
<enum>QFrame::Raised</enum>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_4">
|
<layout class="QGridLayout" name="gridLayout_4">
|
||||||
<property name="leftMargin">
|
<property name="margin">
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>2</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
|
|
|
@ -60,6 +60,7 @@
|
||||||
#define CIRCLEGROUP_CIRCLE_COL_GROUPNAME 0
|
#define CIRCLEGROUP_CIRCLE_COL_GROUPNAME 0
|
||||||
#define CIRCLEGROUP_CIRCLE_COL_GROUPID 1
|
#define CIRCLEGROUP_CIRCLE_COL_GROUPID 1
|
||||||
#define CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS 2
|
#define CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS 2
|
||||||
|
#define CIRCLEGROUP_CIRCLE_COL_SUBSCRIBEFLAGS 3
|
||||||
|
|
||||||
#define CIRCLEGROUP_FRIEND_COL_NAME 0
|
#define CIRCLEGROUP_FRIEND_COL_NAME 0
|
||||||
#define CIRCLEGROUP_FRIEND_COL_ID 1
|
#define CIRCLEGROUP_FRIEND_COL_ID 1
|
||||||
|
@ -95,6 +96,11 @@
|
||||||
|
|
||||||
#define IMAGE_EDIT ":/images/edit_16.png"
|
#define IMAGE_EDIT ":/images/edit_16.png"
|
||||||
#define IMAGE_CREATE ":/icons/circle_new_128.png"
|
#define IMAGE_CREATE ":/icons/circle_new_128.png"
|
||||||
|
#define IMAGE_INVITED ":/icons/bullet_yellow_128.png"
|
||||||
|
#define IMAGE_MEMBER ":/icons/bullet_green_128.png"
|
||||||
|
|
||||||
|
// comment this out in order to remove the sorting of circles into "belong to" and "other visible circles"
|
||||||
|
#define CIRCLE_MEMBERSHIP_CATEGORIES 1
|
||||||
|
|
||||||
// quick solution for RSID_COL_VOTES sorting
|
// quick solution for RSID_COL_VOTES sorting
|
||||||
class TreeWidgetItem : public QTreeWidgetItem {
|
class TreeWidgetItem : public QTreeWidgetItem {
|
||||||
|
@ -141,7 +147,7 @@ IdDialog::IdDialog(QWidget *parent) :
|
||||||
ui->treeWidget_membership->clear();
|
ui->treeWidget_membership->clear();
|
||||||
|
|
||||||
mExternalOtherCircleItem = NULL ;
|
mExternalOtherCircleItem = NULL ;
|
||||||
mExternalSubCircleItem = NULL ;
|
mExternalBelongingCircleItem = NULL ;
|
||||||
|
|
||||||
/* Setup UI helper */
|
/* Setup UI helper */
|
||||||
mStateHelper = new UIStateHelper(this);
|
mStateHelper = new UIStateHelper(this);
|
||||||
|
@ -231,7 +237,7 @@ IdDialog::IdDialog(QWidget *parent) :
|
||||||
|
|
||||||
/* Set initial section sizes */
|
/* Set initial section sizes */
|
||||||
QHeaderView * circlesheader = ui->treeWidget_membership->header () ;
|
QHeaderView * circlesheader = ui->treeWidget_membership->header () ;
|
||||||
circlesheader->resizeSection (CIRCLEGROUP_CIRCLE_COL_GROUPNAME, 280);
|
circlesheader->resizeSection (CIRCLEGROUP_CIRCLE_COL_GROUPNAME, QFontMetricsF(ui->idTreeWidget->font()).width("Circle name")*1.5) ;
|
||||||
|
|
||||||
ui->filterLineEdit->addFilter(QIcon(), tr("ID"), RSID_COL_KEYID, tr("Search ID"));
|
ui->filterLineEdit->addFilter(QIcon(), tr("ID"), RSID_COL_KEYID, tr("Search ID"));
|
||||||
|
|
||||||
|
@ -260,14 +266,20 @@ IdDialog::IdDialog(QWidget *parent) :
|
||||||
|
|
||||||
QString hlp_str = tr(
|
QString hlp_str = tr(
|
||||||
" <h1><img width=\"32\" src=\":/icons/help_64.png\"> Identities</h1> \
|
" <h1><img width=\"32\" src=\":/icons/help_64.png\"> Identities</h1> \
|
||||||
<p>In this tab you can create/edit pseudo-anonymous identities.</p> \
|
<p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> \
|
||||||
<p>Identities are used to securely identify your data: sign forum and channel posts,\
|
<p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts,\
|
||||||
and receive feedback using Retroshare built-in email system, post comments \
|
receive feedback using the Retroshare built-in email system, post comments \
|
||||||
after channel posts, etc.</p> \
|
after channel posts, chat using secured tunnels, etc.</p> \
|
||||||
<p>Identities can optionally be signed by your Retroshare node's certificate. \
|
<p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. \
|
||||||
Signed identities are easier to trust but are easily linked to your node's IP address.</p> \
|
Signed identities are easier to trust but are easily linked to your node's IP address.</p> \
|
||||||
<p> Anonymous identities allow you to anonymously interact with other users. They cannot be \
|
<p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be \
|
||||||
spoofed, but noone can prove who really owns a given identity.</p>") ;
|
spoofed, but noone can prove who really owns a given identity.</p> \
|
||||||
|
<p><b>External circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be \
|
||||||
|
used to restrict the visibility to forums, channels, etc. </p> \
|
||||||
|
<p>An <b>external circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle \
|
||||||
|
or even self-restricted, meaning that it is only visible to its members.</p> \
|
||||||
|
<p>A <b>local circle</b> is a group of friend nodes (represented by their PGP Ids), and can also be used to restrict the \
|
||||||
|
visibility of forums and channels. They are not shared over the network, and their list of members is only visible to you.</p>") ;
|
||||||
|
|
||||||
registerHelpButton(ui->helpButton, hlp_str) ;
|
registerHelpButton(ui->helpButton, hlp_str) ;
|
||||||
|
|
||||||
|
@ -276,7 +288,7 @@ IdDialog::IdDialog(QWidget *parent) :
|
||||||
|
|
||||||
// circles stuff
|
// circles stuff
|
||||||
|
|
||||||
connect(ui->treeWidget_membership, SIGNAL(itemSelectionChanged()), this, SLOT(circle_selected()));
|
//connect(ui->treeWidget_membership, SIGNAL(itemSelectionChanged()), this, SLOT(circle_selected()));
|
||||||
connect(ui->treeWidget_membership, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(CircleListCustomPopupMenu(QPoint)));
|
connect(ui->treeWidget_membership, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(CircleListCustomPopupMenu(QPoint)));
|
||||||
|
|
||||||
|
|
||||||
|
@ -291,7 +303,7 @@ IdDialog::IdDialog(QWidget *parent) :
|
||||||
QTimer *tmer = new QTimer(this) ;
|
QTimer *tmer = new QTimer(this) ;
|
||||||
connect(tmer,SIGNAL(timeout()),this,SLOT(updateCirclesDisplay())) ;
|
connect(tmer,SIGNAL(timeout()),this,SLOT(updateCirclesDisplay())) ;
|
||||||
|
|
||||||
tmer->start(10000) ; // update every minute.
|
tmer->start(10000) ; // update every 10 secs.
|
||||||
}
|
}
|
||||||
|
|
||||||
void IdDialog::updateCirclesDisplay()
|
void IdDialog::updateCirclesDisplay()
|
||||||
|
@ -315,10 +327,10 @@ void IdDialog::requestCircleGroupMeta()
|
||||||
{
|
{
|
||||||
mStateHelper->setLoading(CIRCLESDIALOG_GROUPMETA, true);
|
mStateHelper->setLoading(CIRCLESDIALOG_GROUPMETA, true);
|
||||||
|
|
||||||
//#ifdef ID_DEBUG
|
#ifdef ID_DEBUG
|
||||||
std::cerr << "CirclesDialog::requestGroupMeta()";
|
std::cerr << "CirclesDialog::requestGroupMeta()";
|
||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
//#endif
|
#endif
|
||||||
|
|
||||||
mCircleQueue->cancelActiveRequestTokens(CIRCLESDIALOG_GROUPMETA);
|
mCircleQueue->cancelActiveRequestTokens(CIRCLESDIALOG_GROUPMETA);
|
||||||
|
|
||||||
|
@ -377,27 +389,25 @@ void IdDialog::loadCircleGroupMeta(const uint32_t &token)
|
||||||
//personalCirclesItem->setText(0, tr("Personal Circles"));
|
//personalCirclesItem->setText(0, tr("Personal Circles"));
|
||||||
//ui->treeWidget_membership->addTopLevelItem(personalCirclesItem);
|
//ui->treeWidget_membership->addTopLevelItem(personalCirclesItem);
|
||||||
|
|
||||||
|
#ifdef CIRCLE_MEMBERSHIP_CATEGORIES
|
||||||
if(!mExternalOtherCircleItem)
|
if(!mExternalOtherCircleItem)
|
||||||
{
|
{
|
||||||
mExternalOtherCircleItem = new QTreeWidgetItem();
|
mExternalOtherCircleItem = new QTreeWidgetItem();
|
||||||
mExternalOtherCircleItem->setText(0, tr("Other visible circles"));
|
mExternalOtherCircleItem->setText(0, tr("Other visible external circles"));
|
||||||
|
|
||||||
ui->treeWidget_membership->addTopLevelItem(mExternalOtherCircleItem);
|
ui->treeWidget_membership->addTopLevelItem(mExternalOtherCircleItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!mExternalSubCircleItem )
|
if(!mExternalBelongingCircleItem )
|
||||||
{
|
{
|
||||||
mExternalSubCircleItem = new QTreeWidgetItem();
|
mExternalBelongingCircleItem = new QTreeWidgetItem();
|
||||||
mExternalSubCircleItem->setText(0, tr("Circles I belong to"));
|
mExternalBelongingCircleItem->setText(0, tr("External circles my identities belong to"));
|
||||||
ui->treeWidget_membership->addTopLevelItem(mExternalSubCircleItem);
|
ui->treeWidget_membership->addTopLevelItem(mExternalBelongingCircleItem);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if(!mExternalLocalCircleItem)
|
std::list<RsGxsId> own_identities ;
|
||||||
{
|
rsIdentity->getOwnIds(own_identities) ;
|
||||||
mExternalLocalCircleItem = new QTreeWidgetItem();
|
|
||||||
mExternalLocalCircleItem->setText(0, tr("Local circles"));
|
|
||||||
ui->treeWidget_membership->addTopLevelItem(mExternalLocalCircleItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(vit = groupInfo.begin(); vit != groupInfo.end();++vit)
|
for(vit = groupInfo.begin(); vit != groupInfo.end();++vit)
|
||||||
{
|
{
|
||||||
|
@ -408,17 +418,22 @@ void IdDialog::loadCircleGroupMeta(const uint32_t &token)
|
||||||
rsGxsCircles->getCircleDetails(RsGxsCircleId(vit->mGroupId), details) ;
|
rsGxsCircles->getCircleDetails(RsGxsCircleId(vit->mGroupId), details) ;
|
||||||
|
|
||||||
bool should_re_add = true ;
|
bool should_re_add = true ;
|
||||||
bool subscribed = vit->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED ;
|
|
||||||
bool am_I_in_circle = details.mAmIAllowed ;
|
bool am_I_in_circle = details.mAmIAllowed ;
|
||||||
QTreeWidgetItem *item = NULL ;
|
QTreeWidgetItem *item = NULL ;
|
||||||
|
|
||||||
#ifdef ID_DEBUG
|
#ifdef ID_DEBUG
|
||||||
std::cerr << "Loaded info for circle " << vit->mGroupId << ". ubscribed=" << subscribed << ", am_I_in_circle=" << am_I_in_circle << std::endl;
|
std::cerr << "Loaded info for circle " << vit->mGroupId << ". am_I_in_circle=" << am_I_in_circle << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// find already existing items for this circle
|
// find already existing items for this circle
|
||||||
|
|
||||||
QList<QTreeWidgetItem*> clist = ui->treeWidget_membership->findItems( QString::fromStdString(vit->mGroupId.toStdString()), Qt::MatchExactly|Qt::MatchRecursive, CIRCLEGROUP_CIRCLE_COL_GROUPID);
|
// implement the search manually, because there's no find based on user role.
|
||||||
|
//QList<QTreeWidgetItem*> clist = ui->treeWidget_membership->findItems( QString::fromStdString(vit->mGroupId.toStdString()), Qt::MatchExactly|Qt::MatchRecursive, CIRCLEGROUP_CIRCLE_COL_GROUPID);
|
||||||
|
QList<QTreeWidgetItem*> clist ;
|
||||||
|
QString test_str = QString::fromStdString(vit->mGroupId.toStdString()) ;
|
||||||
|
for(QTreeWidgetItemIterator itt(ui->treeWidget_membership);*itt;++itt)
|
||||||
|
if( (*itt)->data(CIRCLEGROUP_CIRCLE_COL_GROUPID,Qt::UserRole).toString() == test_str)
|
||||||
|
clist.push_back(*itt) ;
|
||||||
|
|
||||||
if(!clist.empty())
|
if(!clist.empty())
|
||||||
{
|
{
|
||||||
|
@ -434,10 +449,11 @@ void IdDialog::loadCircleGroupMeta(const uint32_t &token)
|
||||||
|
|
||||||
item = clist.front() ;
|
item = clist.front() ;
|
||||||
|
|
||||||
if(am_I_in_circle && item->parent() != mExternalSubCircleItem)
|
#ifdef CIRCLE_MEMBERSHIP_CATEGORIES
|
||||||
|
if(am_I_in_circle && item->parent() != mExternalBelongingCircleItem)
|
||||||
{
|
{
|
||||||
#ifdef ID_DEBUG
|
#ifdef ID_DEBUG
|
||||||
std::cerr << " Existing group is not in subscribed items although it is subscribed. Removing." << std::endl;
|
std::cerr << " Existing circle is not in subscribed items although it is subscribed. Removing." << std::endl;
|
||||||
#endif
|
#endif
|
||||||
delete item ;
|
delete item ;
|
||||||
item = NULL ;
|
item = NULL ;
|
||||||
|
@ -445,20 +461,16 @@ void IdDialog::loadCircleGroupMeta(const uint32_t &token)
|
||||||
else if(!am_I_in_circle && item->parent() != mExternalOtherCircleItem)
|
else if(!am_I_in_circle && item->parent() != mExternalOtherCircleItem)
|
||||||
{
|
{
|
||||||
#ifdef ID_DEBUG
|
#ifdef ID_DEBUG
|
||||||
std::cerr << " Existing group is not in subscribed items although it is subscribed. Removing." << std::endl;
|
std::cerr << " Existing circle is not in subscribed items although it is subscribed. Removing." << std::endl;
|
||||||
#endif
|
#endif
|
||||||
delete item ;
|
delete item ;
|
||||||
item = NULL ;
|
item = NULL ;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
should_re_add = false ; // item already exists
|
should_re_add = false ; // item already exists
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (vit->mCircleType == GXS_CIRCLE_TYPE_LOCAL)
|
|
||||||
// {
|
|
||||||
// std::cerr << "(WW) Local circle not added to tree widget. Needs to be implmeented." << std::endl;
|
|
||||||
// continue ;
|
|
||||||
// }
|
|
||||||
/* Add Widget, and request Pages */
|
/* Add Widget, and request Pages */
|
||||||
|
|
||||||
if(should_re_add)
|
if(should_re_add)
|
||||||
|
@ -466,31 +478,43 @@ void IdDialog::loadCircleGroupMeta(const uint32_t &token)
|
||||||
item = new QTreeWidgetItem();
|
item = new QTreeWidgetItem();
|
||||||
|
|
||||||
item->setText(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, QString::fromUtf8(vit->mGroupName.c_str()));
|
item->setText(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, QString::fromUtf8(vit->mGroupName.c_str()));
|
||||||
item->setText(CIRCLEGROUP_CIRCLE_COL_GROUPID, QString::fromStdString(vit->mGroupId.toStdString()));
|
item->setToolTip(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,tr("Circle ID: ")+QString::fromStdString(vit->mGroupId.toStdString()));
|
||||||
|
item->setData(CIRCLEGROUP_CIRCLE_COL_GROUPID,Qt::UserRole, QString::fromStdString(vit->mGroupId.toStdString()));
|
||||||
item->setData(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS, Qt::UserRole, QVariant(vit->mSubscribeFlags));
|
item->setData(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS, Qt::UserRole, QVariant(vit->mSubscribeFlags));
|
||||||
|
#warning TODO
|
||||||
|
//item->setData(CIRCLEGROUP_CIRCLE_COL_SUBSCRIBEFLAGS, Qt::UserRole, QVariant(details.mSubscribeFlags));
|
||||||
|
|
||||||
|
#ifdef CIRCLE_MEMBERSHIP_CATEGORIES
|
||||||
if(am_I_in_circle)
|
if(am_I_in_circle)
|
||||||
{
|
{
|
||||||
#ifdef ID_DEBUG
|
#ifdef ID_DEBUG
|
||||||
std::cerr << " adding item for group " << vit->mGroupId << " to own circles"<< std::endl;
|
std::cerr << " adding item for circle " << vit->mGroupId << " to own circles"<< std::endl;
|
||||||
#endif
|
#endif
|
||||||
mExternalSubCircleItem->addChild(item);
|
mExternalBelongingCircleItem->addChild(item);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef ID_DEBUG
|
#ifdef ID_DEBUG
|
||||||
std::cerr << " adding item for group " << vit->mGroupId << " to others"<< std::endl;
|
std::cerr << " adding item for circle " << vit->mGroupId << " to others"<< std::endl;
|
||||||
#endif
|
#endif
|
||||||
mExternalOtherCircleItem->addChild(item);
|
mExternalOtherCircleItem->addChild(item);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
ui->treeWidget_membership->addTopLevelItem(item) ;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else if(item->text(CIRCLEGROUP_CIRCLE_COL_GROUPNAME) != QString::fromUtf8(vit->mGroupName.c_str()))
|
else if(item->text(CIRCLEGROUP_CIRCLE_COL_GROUPNAME) != QString::fromUtf8(vit->mGroupName.c_str()))
|
||||||
{
|
{
|
||||||
#ifdef ID_DEBUG
|
#ifdef ID_DEBUG
|
||||||
std::cerr << " Existing group has a new name. Updating it in the tree." << std::endl;
|
std::cerr << " Existing circle has a new name. Updating it in the tree." << std::endl;
|
||||||
#endif
|
#endif
|
||||||
item->setText(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, QString::fromUtf8(vit->mGroupName.c_str()));
|
item->setText(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, QString::fromUtf8(vit->mGroupName.c_str()));
|
||||||
}
|
}
|
||||||
|
// just in case.
|
||||||
|
|
||||||
|
item->setData(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS, Qt::UserRole, QVariant(vit->mSubscribeFlags));
|
||||||
|
#warning TODO
|
||||||
|
//item->setData(CIRCLEGROUP_CIRCLE_COL_SUBSCRIBEFLAGS, Qt::UserRole, QVariant(details.mSubscribeFlags));
|
||||||
|
|
||||||
if (vit->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN)
|
if (vit->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN)
|
||||||
{
|
{
|
||||||
|
@ -501,13 +525,122 @@ void IdDialog::loadCircleGroupMeta(const uint32_t &token)
|
||||||
item->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS,font) ;
|
item->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS,font) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// now determine for this circle wether we have pending invites
|
||||||
|
// we add a sub-item to the circle (to show the invite system info) in the following two cases:
|
||||||
|
// - own GXS id is in admin list but not subscribed
|
||||||
|
// - own GXS id is is admin and subscribed
|
||||||
|
// - own GXS id is is subscribed
|
||||||
|
|
||||||
|
bool am_I_invited = false ;
|
||||||
|
bool am_I_pending = false ;
|
||||||
|
#ifdef ID_DEBUG
|
||||||
|
std::cerr << " updating status of all identities for this circle:" << std::endl;
|
||||||
|
#endif
|
||||||
|
//for(std::list<RsGxsId>::const_iterator it(own_identities.begin());it!=own_identities.end();++it)
|
||||||
|
for(std::map<RsGxsId,uint32_t>::const_iterator it(details.mSubscriptionFlags.begin());it!=details.mSubscriptionFlags.end();++it)
|
||||||
|
{
|
||||||
|
#ifdef ID_DEBUG
|
||||||
|
std::cerr << " ID " << *it << ": " ;
|
||||||
|
#endif
|
||||||
|
bool is_own_id = rsIdentity->isOwnId(it->first) ;
|
||||||
|
bool invited ( it->second & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST );
|
||||||
|
bool subscrb ( it->second & GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED );
|
||||||
|
|
||||||
#ifdef ID_DEBUG
|
#ifdef ID_DEBUG
|
||||||
if (subscribed)
|
std::cerr << "invited: " << invited << ", subscription: " << subscrb ;
|
||||||
item->setIcon(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,QIcon(":icons/bullet_green_128.png")) ;
|
|
||||||
else
|
|
||||||
item->setIcon(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,QIcon(":icons/bullet_yellow_128.png")) ;
|
|
||||||
#endif
|
#endif
|
||||||
|
QTreeWidgetItem *subitem = NULL ;
|
||||||
|
|
||||||
|
// see if the item already exists
|
||||||
|
for(uint32_t k=0;k<item->childCount();++k)
|
||||||
|
if(item->child(k)->data(CIRCLEGROUP_CIRCLE_COL_GROUPID,Qt::UserRole).toString().toStdString() == it->first.toStdString())
|
||||||
|
{
|
||||||
|
subitem = item->child(k);
|
||||||
|
#ifdef ID_DEBUG
|
||||||
|
std::cerr << " found existing sub item." << std::endl;
|
||||||
|
#endif
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!(invited || subscrb))
|
||||||
|
{
|
||||||
|
if(subitem != NULL)
|
||||||
|
delete subitem ;
|
||||||
|
#ifdef ID_DEBUG
|
||||||
|
std::cerr << ". not relevant. Skipping." << std::endl;
|
||||||
|
#endif
|
||||||
|
continue ;
|
||||||
|
}
|
||||||
|
// remove item if flags are not ok.
|
||||||
|
|
||||||
|
if(subitem && subitem->data(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS, Qt::UserRole).toUInt() != it->second)
|
||||||
|
{
|
||||||
|
delete subitem ;
|
||||||
|
subitem = NULL ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!subitem)
|
||||||
|
{
|
||||||
|
#ifdef ID_DEBUG
|
||||||
|
std::cerr << " no existing sub item. Creating new one." << std::endl;
|
||||||
|
#endif
|
||||||
|
subitem = new QTreeWidgetItem(item);
|
||||||
|
|
||||||
|
RsIdentityDetails idd ;
|
||||||
|
bool has_id = rsIdentity->getIdDetails(it->first,idd) ;
|
||||||
|
|
||||||
|
QPixmap pixmap ;
|
||||||
|
|
||||||
|
if(idd.mAvatar.mSize == 0 || !pixmap.loadFromData(idd.mAvatar.mData, idd.mAvatar.mSize, "PNG"))
|
||||||
|
pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(it->first)) ;
|
||||||
|
|
||||||
|
if(has_id)
|
||||||
|
subitem->setText(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, QString::fromUtf8(idd.mNickname.c_str())) ;
|
||||||
|
else
|
||||||
|
subitem->setText(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, tr("Unknown ID :")+QString::fromStdString(it->first.toStdString())) ;
|
||||||
|
|
||||||
|
subitem->setToolTip(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, tr("Indentity ID: ")+QString::fromStdString(it->first.toStdString())) ;
|
||||||
|
subitem->setData(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS, Qt::UserRole, QVariant(it->second)) ;
|
||||||
|
subitem->setData(CIRCLEGROUP_CIRCLE_COL_GROUPID, Qt::UserRole, QString::fromStdString(it->first.toStdString())) ;
|
||||||
|
|
||||||
|
subitem->setIcon(RSID_COL_NICKNAME, QIcon(pixmap));
|
||||||
|
|
||||||
|
item->addChild(subitem) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(invited && !subscrb)
|
||||||
|
{
|
||||||
|
subitem->setText(CIRCLEGROUP_CIRCLE_COL_GROUPID, tr("Invited")) ;
|
||||||
|
|
||||||
|
if(is_own_id)
|
||||||
|
am_I_invited = true ;
|
||||||
|
}
|
||||||
|
if(!invited && subscrb)
|
||||||
|
{
|
||||||
|
subitem->setText(CIRCLEGROUP_CIRCLE_COL_GROUPID, tr("Subscription pending")) ;
|
||||||
|
|
||||||
|
if(is_own_id)
|
||||||
|
am_I_pending = true ;
|
||||||
|
}
|
||||||
|
if(invited && subscrb)
|
||||||
|
subitem->setText(CIRCLEGROUP_CIRCLE_COL_GROUPID, tr("Member")) ;
|
||||||
|
|
||||||
|
if (is_own_id)
|
||||||
|
{
|
||||||
|
QFont font = subitem->font(CIRCLEGROUP_CIRCLE_COL_GROUPNAME) ;
|
||||||
|
font.setBold(true) ;
|
||||||
|
subitem->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,font) ;
|
||||||
|
subitem->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPID,font) ;
|
||||||
|
subitem->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS,font) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(am_I_in_circle)
|
||||||
|
item->setIcon(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,QIcon(IMAGE_MEMBER)) ;
|
||||||
|
else if(am_I_invited || am_I_pending)
|
||||||
|
item->setIcon(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,QIcon(IMAGE_INVITED)) ;
|
||||||
|
else
|
||||||
|
item->setIcon(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,QIcon()) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,12 +683,10 @@ void IdDialog::loadCircleGroupData(const uint32_t& token)
|
||||||
|
|
||||||
QTreeWidgetItem *item = ui->treeWidget_membership->currentItem();
|
QTreeWidgetItem *item = ui->treeWidget_membership->currentItem();
|
||||||
|
|
||||||
if ((!item) || (!item->parent()))
|
RsGxsCircleId id ;
|
||||||
|
if(!getItemCircleId(item,id))
|
||||||
return ;
|
return ;
|
||||||
|
|
||||||
QString coltext = item->text(CIRCLEGROUP_CIRCLE_COL_GROUPID);
|
|
||||||
RsGxsCircleId id ( coltext.toStdString()) ;
|
|
||||||
|
|
||||||
if(requested_cid != id)
|
if(requested_cid != id)
|
||||||
{
|
{
|
||||||
std::cerr << "(WW) not the same circle. Dropping request." << std::endl;
|
std::cerr << "(WW) not the same circle. Dropping request." << std::endl;
|
||||||
|
@ -571,6 +702,24 @@ void IdDialog::loadCircleGroupData(const uint32_t& token)
|
||||||
mStateHelper->setLoading(CIRCLESDIALOG_GROUPDATA, false);
|
mStateHelper->setLoading(CIRCLESDIALOG_GROUPDATA, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IdDialog::getItemCircleId(QTreeWidgetItem *item,RsGxsCircleId& id)
|
||||||
|
{
|
||||||
|
#ifdef CIRCLE_MEMBERSHIP_CATEGORIES
|
||||||
|
if ((!item) || (!item->parent()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QString coltext = (item->parent()->parent())? (item->parent()->data(CIRCLEGROUP_CIRCLE_COL_GROUPID,Qt::UserRole).toString()) : (item->data(CIRCLEGROUP_CIRCLE_COL_GROUPID,Qt::UserRole).toString());
|
||||||
|
id = RsGxsCircleId( coltext.toStdString()) ;
|
||||||
|
#else
|
||||||
|
if(!item)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QString coltext = (item->parent())? (item->parent()->data(CIRCLEGROUP_CIRCLE_COL_GROUPID,Qt::UserRole).toString()) : (item->data(CIRCLEGROUP_CIRCLE_COL_GROUPID,Qt::UserRole).toString());
|
||||||
|
id = RsGxsCircleId( coltext.toStdString()) ;
|
||||||
|
#endif
|
||||||
|
return true ;
|
||||||
|
}
|
||||||
|
|
||||||
void IdDialog::createExternalCircle()
|
void IdDialog::createExternalCircle()
|
||||||
{
|
{
|
||||||
CreateCircleDialog dlg;
|
CreateCircleDialog dlg;
|
||||||
|
@ -581,42 +730,186 @@ void IdDialog::createExternalCircle()
|
||||||
}
|
}
|
||||||
void IdDialog::showEditExistingCircle()
|
void IdDialog::showEditExistingCircle()
|
||||||
{
|
{
|
||||||
QTreeWidgetItem *item = ui->treeWidget_membership->currentItem();
|
RsGxsCircleId id ;
|
||||||
if ((!item) || (!item->parent()))
|
|
||||||
{
|
if(!getItemCircleId(ui->treeWidget_membership->currentItem(),id))
|
||||||
return ;
|
return ;
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t subscribe_flags = item->data(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS, Qt::UserRole).toUInt();
|
uint32_t subscribe_flags = ui->treeWidget_membership->currentItem()->data(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS, Qt::UserRole).toUInt();
|
||||||
|
|
||||||
QString coltext = item->text(CIRCLEGROUP_CIRCLE_COL_GROUPID);
|
|
||||||
RsGxsGroupId id ( coltext.toStdString());
|
|
||||||
|
|
||||||
CreateCircleDialog dlg;
|
CreateCircleDialog dlg;
|
||||||
|
|
||||||
dlg.editExistingId(id,true,!(subscribe_flags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN)) ;
|
dlg.editExistingId(RsGxsGroupId(id),true,!(subscribe_flags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN)) ;
|
||||||
dlg.exec();
|
dlg.exec();
|
||||||
|
|
||||||
requestCircleGroupMeta(); // update GUI
|
requestCircleGroupMeta(); // update GUI
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IdDialog::acceptCircleSubscription()
|
||||||
|
{
|
||||||
|
RsGxsCircleId circle_id ;
|
||||||
|
|
||||||
|
if(!getItemCircleId(ui->treeWidget_membership->currentItem(),circle_id))
|
||||||
|
return;
|
||||||
|
|
||||||
|
RsGxsId own_id(qobject_cast<QAction*>(sender())->data().toString().toStdString());
|
||||||
|
|
||||||
|
rsGxsCircles->requestCircleMembership(own_id,circle_id) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IdDialog::cancelCircleSubscription()
|
||||||
|
{
|
||||||
|
RsGxsCircleId circle_id ;
|
||||||
|
|
||||||
|
if(!getItemCircleId(ui->treeWidget_membership->currentItem(),circle_id))
|
||||||
|
return;
|
||||||
|
|
||||||
|
RsGxsId own_id(qobject_cast<QAction*>(sender())->data().toString().toStdString());
|
||||||
|
|
||||||
|
rsGxsCircles->cancelCircleMembership(own_id,circle_id) ;
|
||||||
|
}
|
||||||
|
|
||||||
void IdDialog::CircleListCustomPopupMenu( QPoint )
|
void IdDialog::CircleListCustomPopupMenu( QPoint )
|
||||||
{
|
{
|
||||||
QMenu contextMnu( this );
|
QMenu contextMnu( this );
|
||||||
|
|
||||||
|
RsGxsCircleId circle_id ;
|
||||||
QTreeWidgetItem *item = ui->treeWidget_membership->currentItem();
|
QTreeWidgetItem *item = ui->treeWidget_membership->currentItem();
|
||||||
|
|
||||||
contextMnu.addAction(QIcon(IMAGE_CREATE), tr("Create Circle"), this, SLOT(createExternalCircle()));
|
if(!getItemCircleId(item,circle_id))
|
||||||
|
return ;
|
||||||
|
|
||||||
if (item)
|
RsGxsId current_gxs_id ;
|
||||||
|
RsGxsId item_id(item->data(CIRCLEGROUP_CIRCLE_COL_GROUPID,Qt::UserRole).toString().toStdString());
|
||||||
|
bool is_circle ;
|
||||||
|
|
||||||
|
if(item_id == RsGxsId(circle_id)) // is it a circle?
|
||||||
{
|
{
|
||||||
uint32_t subscribe_flags = item->data(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS, Qt::UserRole).toUInt();
|
uint32_t group_flags = item->data(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS, Qt::UserRole).toUInt();
|
||||||
|
|
||||||
|
#ifdef CIRCLE_MEMBERSHIP_CATEGORIES
|
||||||
if(item->parent() != NULL)
|
if(item->parent() != NULL)
|
||||||
if(subscribe_flags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN)
|
{
|
||||||
|
#endif
|
||||||
|
if(group_flags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN)
|
||||||
contextMnu.addAction(QIcon(IMAGE_EDIT), tr("Edit Circle"), this, SLOT(showEditExistingCircle()));
|
contextMnu.addAction(QIcon(IMAGE_EDIT), tr("Edit Circle"), this, SLOT(showEditExistingCircle()));
|
||||||
else
|
else
|
||||||
contextMnu.addAction(QIcon(IMAGE_EDIT), tr("See details"), this, SLOT(showEditExistingCircle()));
|
contextMnu.addAction(QIcon(IMAGE_EDIT), tr("See details"), this, SLOT(showEditExistingCircle()));
|
||||||
|
#ifdef CIRCLE_MEMBERSHIP_CATEGORIES
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::cerr << " Item is a circle item. Adding Edit/Details menu entry." << std::endl;
|
||||||
|
is_circle = true ;
|
||||||
|
|
||||||
|
contextMnu.addSeparator() ;
|
||||||
|
}
|
||||||
|
else if(rsIdentity->isOwnId(item_id)) // is it one of our GXS ids?
|
||||||
|
{
|
||||||
|
current_gxs_id = RsGxsId(item_id);
|
||||||
|
is_circle =false ;
|
||||||
|
|
||||||
|
std::cerr << " Item is a GxsId item. Requesting flags/group id from parent: " << circle_id << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
RsGxsCircleDetails details ;
|
||||||
|
|
||||||
|
if(!rsGxsCircles->getCircleDetails(circle_id,details))// grab real circle ID from parent. Make sure circle id is used correctly afterwards!
|
||||||
|
{
|
||||||
|
std::cerr << " (EE) cannot get circle info for ID " << circle_id << ". Not in cache?" << std::endl;
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const int REQUES = 0 ; // Admin list: no Subscription request: no
|
||||||
|
static const int ACCEPT = 1 ; // Admin list: yes Subscription request: no
|
||||||
|
static const int REMOVE = 2 ; // Admin list: yes Subscription request: yes
|
||||||
|
static const int CANCEL = 3 ; // Admin list: no Subscription request: yes
|
||||||
|
|
||||||
|
const QString menu_titles[4] = { tr("Request subscription"), tr("Accept circle invitation"), tr("Quit this circle"),tr("Cancel subscribe request")} ;
|
||||||
|
const QString image_names[4] = { ":/images/edit_16.png",":/images/edit_16.png",":/images/edit_16.png",":/images/edit_16.png" } ;
|
||||||
|
|
||||||
|
std::vector< std::vector<RsGxsId> > ids(4) ;
|
||||||
|
|
||||||
|
std::list<RsGxsId> own_identities ;
|
||||||
|
rsIdentity->getOwnIds(own_identities) ;
|
||||||
|
|
||||||
|
// policy is:
|
||||||
|
// - if on a circle item
|
||||||
|
// => add possible subscription requests for all ids
|
||||||
|
// - if on a Id item
|
||||||
|
// => only add subscription requests for that ID
|
||||||
|
|
||||||
|
for(std::list<RsGxsId>::const_iterator it(own_identities.begin());it!=own_identities.end();++it)
|
||||||
|
if(is_circle || current_gxs_id == *it)
|
||||||
|
{
|
||||||
|
std::map<RsGxsId,uint32_t>::const_iterator vit = details.mSubscriptionFlags.find(*it) ;
|
||||||
|
uint32_t subscribe_flags = (vit == details.mSubscriptionFlags.end())?0:(vit->second) ;
|
||||||
|
|
||||||
|
if(subscribe_flags & GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED)
|
||||||
|
if(subscribe_flags & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST)
|
||||||
|
ids[REMOVE].push_back(*it) ;
|
||||||
|
else
|
||||||
|
ids[CANCEL].push_back(*it) ;
|
||||||
|
else
|
||||||
|
if(subscribe_flags & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST)
|
||||||
|
ids[ACCEPT].push_back(*it) ;
|
||||||
|
else
|
||||||
|
ids[REQUES].push_back(*it) ;
|
||||||
|
}
|
||||||
|
contextMnu.addSeparator() ;
|
||||||
|
|
||||||
|
for(int i=0;i<4;++i)
|
||||||
|
{
|
||||||
|
if(ids[i].size() == 1)
|
||||||
|
{
|
||||||
|
RsIdentityDetails det ;
|
||||||
|
QString id_name ;
|
||||||
|
if(rsIdentity->getIdDetails(ids[i][0],det))
|
||||||
|
id_name = tr("for identity ")+QString::fromUtf8(det.mNickname.c_str()) + "(ID=" + QString::fromStdString(ids[i][0].toStdString()) + ")" ;
|
||||||
|
else
|
||||||
|
id_name = tr("for identity ")+QString::fromStdString(ids[i][0].toStdString()) ;
|
||||||
|
|
||||||
|
QAction *action ;
|
||||||
|
|
||||||
|
if(is_circle)
|
||||||
|
action = new QAction(QIcon(image_names[i]), menu_titles[i] + " " + id_name,this) ;
|
||||||
|
else
|
||||||
|
action = new QAction(QIcon(image_names[i]), menu_titles[i],this) ;
|
||||||
|
|
||||||
|
if(i <2)
|
||||||
|
QObject::connect(action,SIGNAL(triggered()), this, SLOT(acceptCircleSubscription()));
|
||||||
|
else
|
||||||
|
QObject::connect(action,SIGNAL(triggered()), this, SLOT(cancelCircleSubscription()));
|
||||||
|
|
||||||
|
action->setData(QString::fromStdString(ids[i][0].toStdString()));
|
||||||
|
contextMnu.addAction(action) ;
|
||||||
|
}
|
||||||
|
else if(ids[i].size() > 1)
|
||||||
|
{
|
||||||
|
QMenu *menu = new QMenu(menu_titles[i],this) ;
|
||||||
|
|
||||||
|
for(uint32_t j=0;j<ids[i].size();++j)
|
||||||
|
{
|
||||||
|
RsIdentityDetails det ;
|
||||||
|
QString id_name ;
|
||||||
|
if(rsIdentity->getIdDetails(ids[i][j],det))
|
||||||
|
id_name = tr("for identity ")+QString::fromUtf8(det.mNickname.c_str()) + "(ID=" + QString::fromStdString(ids[i][j].toStdString()) + ")" ;
|
||||||
|
else
|
||||||
|
id_name = tr("for identity ")+QString::fromStdString(ids[i][j].toStdString()) ;
|
||||||
|
|
||||||
|
QAction *action = new QAction(QIcon(image_names[i]), id_name,this) ;
|
||||||
|
|
||||||
|
if(i <2)
|
||||||
|
QObject::connect(action,SIGNAL(triggered()), this, SLOT(acceptCircleSubscription()));
|
||||||
|
else
|
||||||
|
QObject::connect(action,SIGNAL(triggered()), this, SLOT(cancelCircleSubscription()));
|
||||||
|
|
||||||
|
action->setData(QString::fromStdString(ids[i][j].toStdString()));
|
||||||
|
menu->addAction(action) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
contextMnu.addMenu(menu) ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contextMnu.exec(QCursor::pos());
|
contextMnu.exec(QCursor::pos());
|
||||||
|
@ -690,7 +983,7 @@ static void check_mark_item(QTreeWidgetItem *item, const std::set<RsPgpId> &name
|
||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
void IdDialog::circle_selected()
|
void IdDialog::circle_selected()
|
||||||
{
|
{
|
||||||
QTreeWidgetItem *item = ui->treeWidget_membership->currentItem();
|
QTreeWidgetItem *item = ui->treeWidget_membership->currentItem();
|
||||||
|
@ -699,32 +992,14 @@ void IdDialog::circle_selected()
|
||||||
std::cerr << "CirclesDialog::circle_selected() valid circle chosen";
|
std::cerr << "CirclesDialog::circle_selected() valid circle chosen";
|
||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((!item) || (!item->parent()))
|
|
||||||
{
|
|
||||||
//mStateHelper->setWidgetEnabled(ui->pushButton_editCircle, false);
|
|
||||||
//ui->pushButton_editCircle->setText(tr("Show details")) ;
|
|
||||||
//ui->pushButton_editCircle->setEnabled(false) ;
|
|
||||||
mark_matching_tree(ui->idTreeWidget, std::set<RsGxsId>(), RSID_COL_KEYID) ;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#ifdef TO_REMOVE
|
|
||||||
uint32_t subscribe_flags = item->data(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS, Qt::UserRole).toUInt();
|
|
||||||
ui->pushButton_editCircle->setEnabled(true) ;
|
|
||||||
|
|
||||||
if(subscribe_flags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN)
|
|
||||||
ui->pushButton_editCircle->setText(tr("Edit circle")) ;
|
|
||||||
else
|
|
||||||
ui->pushButton_editCircle->setText(tr("Show details")) ;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//set_item_background(item, BLUE_BACKGROUND);
|
//set_item_background(item, BLUE_BACKGROUND);
|
||||||
|
|
||||||
QString coltext = item->text(CIRCLEGROUP_CIRCLE_COL_GROUPID);
|
QString coltext = (item->parent()->parent())? (item->parent()->data(CIRCLEGROUP_CIRCLE_COL_GROUPID,Qt::UserRole).toString()) : (item->data(CIRCLEGROUP_CIRCLE_COL_GROUPID,Qt::UserRole).toString());
|
||||||
RsGxsCircleId id ( coltext.toStdString()) ;
|
RsGxsCircleId id ( coltext.toStdString()) ;
|
||||||
|
|
||||||
requestCircleGroupData(id) ;
|
requestCircleGroupData(id) ;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
IdDialog::~IdDialog()
|
IdDialog::~IdDialog()
|
||||||
{
|
{
|
||||||
|
|
|
@ -61,12 +61,16 @@ protected:
|
||||||
|
|
||||||
void requestCircleGroupMeta();
|
void requestCircleGroupMeta();
|
||||||
void requestCircleGroupData(const RsGxsCircleId& circle_id);
|
void requestCircleGroupData(const RsGxsCircleId& circle_id);
|
||||||
|
bool getItemCircleId(QTreeWidgetItem *item,RsGxsCircleId& id) ;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void createExternalCircle();
|
void createExternalCircle();
|
||||||
void showEditExistingCircle();
|
void showEditExistingCircle();
|
||||||
void updateCirclesDisplay();
|
void updateCirclesDisplay();
|
||||||
|
|
||||||
|
void acceptCircleSubscription() ;
|
||||||
|
void cancelCircleSubscription() ;
|
||||||
|
|
||||||
void filterComboBoxChanged();
|
void filterComboBoxChanged();
|
||||||
void filterChanged(const QString &text);
|
void filterChanged(const QString &text);
|
||||||
|
|
||||||
|
@ -85,7 +89,9 @@ private slots:
|
||||||
void IdListCustomPopupMenu( QPoint point );
|
void IdListCustomPopupMenu( QPoint point );
|
||||||
|
|
||||||
void CircleListCustomPopupMenu(QPoint point) ;
|
void CircleListCustomPopupMenu(QPoint point) ;
|
||||||
|
#ifdef SUSPENDED
|
||||||
void circle_selected() ;
|
void circle_selected() ;
|
||||||
|
#endif
|
||||||
|
|
||||||
void addtoContacts();
|
void addtoContacts();
|
||||||
void removefromContacts();
|
void removefromContacts();
|
||||||
|
@ -124,9 +130,8 @@ private:
|
||||||
QTreeWidgetItem *contactsItem;
|
QTreeWidgetItem *contactsItem;
|
||||||
QTreeWidgetItem *allItem;
|
QTreeWidgetItem *allItem;
|
||||||
QTreeWidgetItem *ownItem;
|
QTreeWidgetItem *ownItem;
|
||||||
QTreeWidgetItem *mExternalSubCircleItem;
|
QTreeWidgetItem *mExternalBelongingCircleItem;
|
||||||
QTreeWidgetItem *mExternalOtherCircleItem;
|
QTreeWidgetItem *mExternalOtherCircleItem;
|
||||||
QTreeWidgetItem *mExternalLocalCircleItem;
|
|
||||||
RsGxsUpdateBroadcastBase *mCirclesBroadcastBase ;
|
RsGxsUpdateBroadcastBase *mCirclesBroadcastBase ;
|
||||||
|
|
||||||
RsGxsGroupId mId;
|
RsGxsGroupId mId;
|
||||||
|
|
|
@ -20,16 +20,7 @@
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_6">
|
<layout class="QGridLayout" name="gridLayout_6">
|
||||||
<property name="leftMargin">
|
<property name="margin">
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
|
@ -47,16 +38,7 @@
|
||||||
<enum>QFrame::Sunken</enum>
|
<enum>QFrame::Sunken</enum>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<property name="leftMargin">
|
<property name="margin">
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>2</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
|
@ -147,16 +129,7 @@
|
||||||
<enum>QFrame::Sunken</enum>
|
<enum>QFrame::Sunken</enum>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<property name="leftMargin">
|
<property name="margin">
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>1</number>
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
|
@ -284,7 +257,7 @@
|
||||||
<string>Reputation</string>
|
<string>Reputation</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="textAlignment">
|
<property name="textAlignment">
|
||||||
<set>AlignLeading|AlignVCenter</set>
|
<set>AlignLeft|AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
</column>
|
</column>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -361,16 +334,7 @@
|
||||||
<layout class="QGridLayout" name="gridLayout_3">
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<property name="leftMargin">
|
<property name="margin">
|
||||||
<number>6</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>6</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>6</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>6</number>
|
<number>6</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
|
@ -544,16 +508,7 @@
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
<property name="leftMargin">
|
<property name="margin">
|
||||||
<number>6</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>6</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>6</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>6</number>
|
<number>6</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
|
@ -730,12 +685,12 @@ p, li { white-space: pre-wrap; }
|
||||||
</property>
|
</property>
|
||||||
<column>
|
<column>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Name</string>
|
<string>Circle name</string>
|
||||||
</property>
|
</property>
|
||||||
</column>
|
</column>
|
||||||
<column>
|
<column>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>IDs</string>
|
<string>Membership</string>
|
||||||
</property>
|
</property>
|
||||||
</column>
|
</column>
|
||||||
<item>
|
<item>
|
||||||
|
|
|
@ -38,6 +38,17 @@ CircleWidget::~CircleWidget()
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool same_RsGxsCircleDetails(const RsGxsCircleDetails& d1,const RsGxsCircleDetails& d2)
|
||||||
|
{
|
||||||
|
return ( d1.mCircleId == d2.mCircleId
|
||||||
|
&& d1.mCircleName == d2.mCircleName
|
||||||
|
&& d1.mCircleType == d2.mCircleType
|
||||||
|
&& d1.mSubscriptionFlags == d2.mSubscriptionFlags
|
||||||
|
&& d1.mAllowedGxsIds== d2.mAllowedGxsIds
|
||||||
|
&& d1.mAllowedNodes == d2.mAllowedNodes
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void CircleWidget::updateData(const RsGroupMetaData& gxs_group_info
|
void CircleWidget::updateData(const RsGroupMetaData& gxs_group_info
|
||||||
, const RsGxsCircleDetails& details)
|
, const RsGxsCircleDetails& details)
|
||||||
{
|
{
|
||||||
|
@ -49,40 +60,40 @@ void CircleWidget::updateData(const RsGroupMetaData& gxs_group_info
|
||||||
ui->label->setText(m_myName);
|
ui->label->setText(m_myName);
|
||||||
ui->label->setToolTip(m_myName);
|
ui->label->setToolTip(m_myName);
|
||||||
update();
|
update();
|
||||||
//}//if (_group_info != gxs_group_info)
|
//}
|
||||||
|
|
||||||
if (_circle_details != details) {
|
if(!same_RsGxsCircleDetails(_circle_details , details))
|
||||||
|
{
|
||||||
_circle_details=details;
|
_circle_details=details;
|
||||||
typedef std::set<RsGxsId>::iterator itUnknownPeers;
|
typedef std::set<RsGxsId>::iterator itUnknownPeers;
|
||||||
for (itUnknownPeers it = _circle_details.mAllowedAnonPeers.begin()
|
for (itUnknownPeers it = _circle_details.mAllowedGxsIds.begin()
|
||||||
; it != _circle_details.mAllowedAnonPeers.end()
|
; it != _circle_details.mAllowedGxsIds.end()
|
||||||
; ++it) {
|
; ++it) {
|
||||||
RsGxsId gxs_id = *it;
|
RsGxsId gxs_id = *it;
|
||||||
if(!gxs_id.isNull()) {
|
if(!gxs_id.isNull()) {
|
||||||
emit askForGXSIdentityWidget(gxs_id);
|
emit askForGXSIdentityWidget(gxs_id);
|
||||||
}//if(!gxs_id.isNull())
|
}
|
||||||
}//for (itUnknownPeers it = _circle_details.mUnknownPeers.begin()
|
}
|
||||||
|
|
||||||
typedef std::map<RsPgpId, std::set<RsGxsId> >::const_iterator itAllowedPeers;
|
typedef std::set<RsPgpId>::const_iterator itAllowedPeers;
|
||||||
for (itAllowedPeers it = _circle_details.mAllowedSignedPeers.begin() ; it != _circle_details.mAllowedSignedPeers.end() ; ++it )
|
for (itAllowedPeers it = _circle_details.mAllowedNodes.begin() ; it != _circle_details.mAllowedNodes.end() ; ++it )
|
||||||
{
|
{
|
||||||
RsPgpId pgp_id = it->first;
|
RsPgpId pgp_id = *it;
|
||||||
emit askForPGPIdentityWidget(pgp_id);
|
emit askForPGPIdentityWidget(pgp_id);
|
||||||
|
|
||||||
std::set<RsGxsId> gxs_id_list = it->second;
|
// std::set<RsGxsId> gxs_id_list = it->second;
|
||||||
typedef std::set<RsGxsId>::const_iterator itGxsId;
|
// typedef std::set<RsGxsId>::const_iterator itGxsId;
|
||||||
for (itGxsId curs=gxs_id_list.begin()
|
// for (itGxsId curs=gxs_id_list.begin(); curs != gxs_id_list.end(); ++curs)
|
||||||
; curs != gxs_id_list.end()
|
// {
|
||||||
; ++curs) {
|
// RsGxsId gxs_id = *curs;
|
||||||
RsGxsId gxs_id = *curs;
|
// if(!gxs_id.isNull())
|
||||||
if(!gxs_id.isNull()) {
|
// emit askForGXSIdentityWidget(gxs_id);
|
||||||
emit askForGXSIdentityWidget(gxs_id);
|
// }
|
||||||
}//if(!gxs_id.isNull())
|
// }
|
||||||
}//for (itGxsId curs=gxs_id_list.begin()
|
}
|
||||||
}//for (itAllowedPeers it = _circle_details.mAllowedPeers.begin()
|
|
||||||
|
|
||||||
update();
|
update();
|
||||||
}//if (details!=_circle_details)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize CircleWidget::sizeHint()
|
QSize CircleWidget::sizeHint()
|
||||||
|
|
|
@ -286,7 +286,7 @@ void PeopleDialog::insertCircles(uint32_t token)
|
||||||
continue ;
|
continue ;
|
||||||
}//if(!rsGxsCircles->getCircleDetails(RsGxsCircleId(git->mGroupId), details))
|
}//if(!rsGxsCircles->getCircleDetails(RsGxsCircleId(git->mGroupId), details))
|
||||||
|
|
||||||
if (!details.mIsExternal){
|
if (details.mCircleType != GXS_CIRCLE_TYPE_EXTERNAL){
|
||||||
std::map<RsGxsGroupId, CircleWidget*>::iterator itFound;
|
std::map<RsGxsGroupId, CircleWidget*>::iterator itFound;
|
||||||
if((itFound=_int_circles_widgets.find(gsItem.mGroupId)) == _int_circles_widgets.end()) {
|
if((itFound=_int_circles_widgets.find(gsItem.mGroupId)) == _int_circles_widgets.end()) {
|
||||||
std::cerr << "PeopleDialog::insertExtCircles() add new Internal GroupId: " << gsItem.mGroupId;
|
std::cerr << "PeopleDialog::insertExtCircles() add new Internal GroupId: " << gsItem.mGroupId;
|
||||||
|
|
|
@ -441,7 +441,7 @@ void GxsGroupDialog::updateFromExistingMeta(const QString &description)
|
||||||
|
|
||||||
switch(mGrpMeta.mCircleType)
|
switch(mGrpMeta.mCircleType)
|
||||||
{
|
{
|
||||||
case GXS_CIRCLE_TYPE_YOUREYESONLY:
|
case GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY:
|
||||||
ui.typeLocal->setChecked(true);
|
ui.typeLocal->setChecked(true);
|
||||||
distribution_string = tr("Your friends only") ;
|
distribution_string = tr("Your friends only") ;
|
||||||
ui.localComboBox->loadCircles(GXS_CIRCLE_CHOOSER_PERSONAL, mGrpMeta.mInternalCircle);
|
ui.localComboBox->loadCircles(GXS_CIRCLE_CHOOSER_PERSONAL, mGrpMeta.mInternalCircle);
|
||||||
|
@ -740,7 +740,7 @@ bool GxsGroupDialog::setCircleParameters(RsGroupMetaData &meta)
|
||||||
}
|
}
|
||||||
else if (ui.typeLocal->isChecked())
|
else if (ui.typeLocal->isChecked())
|
||||||
{
|
{
|
||||||
meta.mCircleType = GXS_CIRCLE_TYPE_YOUREYESONLY;
|
meta.mCircleType = GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY;
|
||||||
meta.mCircleId.clear();
|
meta.mCircleId.clear();
|
||||||
meta.mOriginator.clear();
|
meta.mOriginator.clear();
|
||||||
meta.mInternalCircle.clear() ;
|
meta.mInternalCircle.clear() ;
|
||||||
|
|
|
@ -288,7 +288,7 @@ void GxsChannelPostsWidget::insertChannelDetails(const RsGxsChannelGroup &group)
|
||||||
distrib_string = tr("Restricted to members of circle ")+QString::fromStdString(group.mMeta.mCircleId.toStdString()) ;
|
distrib_string = tr("Restricted to members of circle ")+QString::fromStdString(group.mMeta.mCircleId.toStdString()) ;
|
||||||
}
|
}
|
||||||
break ;
|
break ;
|
||||||
case GXS_CIRCLE_TYPE_YOUREYESONLY: distrib_string = tr("Your eyes only");
|
case GXS_CIRCLE_TYPE_YOUR_EYES_ONLY: distrib_string = tr("Your eyes only");
|
||||||
break ;
|
break ;
|
||||||
case GXS_CIRCLE_TYPE_LOCAL: distrib_string = tr("You and your friend nodes");
|
case GXS_CIRCLE_TYPE_LOCAL: distrib_string = tr("You and your friend nodes");
|
||||||
break ;
|
break ;
|
||||||
|
|
|
@ -817,7 +817,7 @@ void GxsForumThreadWidget::insertGroupData()
|
||||||
distrib_string = tr("Restricted to members of circle ")+QString::fromStdString(group.mMeta.mCircleId.toStdString()) ;
|
distrib_string = tr("Restricted to members of circle ")+QString::fromStdString(group.mMeta.mCircleId.toStdString()) ;
|
||||||
}
|
}
|
||||||
break ;
|
break ;
|
||||||
case GXS_CIRCLE_TYPE_YOUREYESONLY: distrib_string = tr("Your eyes only");
|
case GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY: distrib_string = tr("Your eyes only");
|
||||||
break ;
|
break ;
|
||||||
case GXS_CIRCLE_TYPE_LOCAL: distrib_string = tr("You and your friend nodes");
|
case GXS_CIRCLE_TYPE_LOCAL: distrib_string = tr("You and your friend nodes");
|
||||||
break ;
|
break ;
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
<file>icons/blank_green_128.png</file>
|
<file>icons/blank_green_128.png</file>
|
||||||
<file>icons/browsable_blue_128.png</file>
|
<file>icons/browsable_blue_128.png</file>
|
||||||
<file>icons/browsable_green_128.png</file>
|
<file>icons/browsable_green_128.png</file>
|
||||||
|
<file>icons/bullet_blue_128.png</file>
|
||||||
<file>icons/bullet_green_128.png</file>
|
<file>icons/bullet_green_128.png</file>
|
||||||
<file>icons/bullet_grey_128.png</file>
|
<file>icons/bullet_grey_128.png</file>
|
||||||
<file>icons/bullet_red_128.png</file>
|
<file>icons/bullet_red_128.png</file>
|
||||||
|
|
BIN
retroshare-gui/src/gui/icons/bullet_blue_128.png
Normal file
BIN
retroshare-gui/src/gui/icons/bullet_blue_128.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.2 KiB |
|
@ -214,7 +214,7 @@ bool GxsPeerNode::createIdentity(const std::string &name,
|
||||||
|
|
||||||
switch(circleType)
|
switch(circleType)
|
||||||
{
|
{
|
||||||
case GXS_CIRCLE_TYPE_YOUREYESONLY:
|
case GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY:
|
||||||
id.mMeta.mInternalCircle = circleId;
|
id.mMeta.mInternalCircle = circleId;
|
||||||
break;
|
break;
|
||||||
case GXS_CIRCLE_TYPE_LOCAL:
|
case GXS_CIRCLE_TYPE_LOCAL:
|
||||||
|
@ -283,7 +283,7 @@ bool GxsPeerNode::createCircle(const std::string &name,
|
||||||
// THIS is for LOCAL Storage....
|
// THIS is for LOCAL Storage....
|
||||||
grp1.mLocalFriends = localMembers;
|
grp1.mLocalFriends = localMembers;
|
||||||
break;
|
break;
|
||||||
case GXS_CIRCLE_TYPE_YOUREYESONLY:
|
case GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY:
|
||||||
// Circle shouldn't use this.
|
// Circle shouldn't use this.
|
||||||
// but could potentially.
|
// but could potentially.
|
||||||
grp1.mMeta.mInternalCircle = circleId;
|
grp1.mMeta.mInternalCircle = circleId;
|
||||||
|
@ -343,7 +343,7 @@ bool GxsPeerNode::createGroup(const std::string &name,
|
||||||
|
|
||||||
switch(circleType)
|
switch(circleType)
|
||||||
{
|
{
|
||||||
case GXS_CIRCLE_TYPE_YOUREYESONLY:
|
case GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY:
|
||||||
grp1.mMeta.mInternalCircle = circleId;
|
grp1.mMeta.mInternalCircle = circleId;
|
||||||
break;
|
break;
|
||||||
case GXS_CIRCLE_TYPE_LOCAL:
|
case GXS_CIRCLE_TYPE_LOCAL:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue