added backend for distant message and distant chat filtering based on contact list

This commit is contained in:
csoler 2015-12-25 22:37:06 -05:00
parent f5c2aa31e3
commit 140205108a
20 changed files with 373 additions and 180 deletions

View File

@ -25,6 +25,7 @@
#include <unistd.h> #include <unistd.h>
#include <sstream>
#include "openssl/rand.h" #include "openssl/rand.h"
#include "openssl/dh.h" #include "openssl/dh.h"
@ -108,6 +109,17 @@ void DistantChatService::handleRecvChatStatusItem(RsChatStatusItem *cs)
std::cerr << "DistantChatService::handleRecvChatStatusItem(): received keep alive packet for inactive chat! peerId=" << cs->PeerId() << std::endl; std::cerr << "DistantChatService::handleRecvChatStatusItem(): received keep alive packet for inactive chat! peerId=" << cs->PeerId() << std::endl;
} }
bool DistantChatService::acceptDataFromPeer(const RsGxsId& gxs_id)
{
if(mDistantChatPermissions & RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NON_CONTACTS)
return (rsIdentity!=NULL) && rsIdentity->isARegularContact(gxs_id) ;
if(mDistantChatPermissions & RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_EVERYBODY)
return false ;
return true ;
}
void DistantChatService::notifyTunnelStatus(const RsGxsTunnelService::RsGxsTunnelId &tunnel_id, uint32_t tunnel_status) void DistantChatService::notifyTunnelStatus(const RsGxsTunnelService::RsGxsTunnelId &tunnel_id, uint32_t tunnel_status)
{ {
std::cerr << "DistantChatService::notifyTunnelStatus(): got notification " << std::hex << tunnel_status << std::dec << " for tunnel " << tunnel_id << std::endl; std::cerr << "DistantChatService::notifyTunnelStatus(): got notification " << std::hex << tunnel_status << std::dec << " for tunnel " << tunnel_id << std::endl;
@ -137,9 +149,7 @@ void DistantChatService::receiveData(const RsGxsTunnelService::RsGxsTunnelId &tu
std::cerr << "DistantChatService::receiveData(): got data of size " << data_size << " for tunnel " << tunnel_id << std::endl; std::cerr << "DistantChatService::receiveData(): got data of size " << data_size << " for tunnel " << tunnel_id << std::endl;
std::cerr << " received: " << RsUtil::BinToHex(data,data_size) << std::endl; std::cerr << " received: " << RsUtil::BinToHex(data,data_size) << std::endl;
std::cerr << " deserialising..." << std::endl; std::cerr << " deserialising..." << std::endl;
RsItem *item = RsChatSerialiser().deserialise(data,&data_size) ;
// always make the contact up to date. This is useful for server side, which doesn't know about the chat until it // always make the contact up to date. This is useful for server side, which doesn't know about the chat until it
// receives the first item. // receives the first item.
{ {
@ -149,21 +159,26 @@ void DistantChatService::receiveData(const RsGxsTunnelService::RsGxsTunnelId &tu
if(!mGxsTunnels->getTunnelInfo(tunnel_id,tinfo)) if(!mGxsTunnels->getTunnelInfo(tunnel_id,tinfo))
return ; return ;
// Check if the data is accepted. We cannot prevent the creation of tunnels at the level of p3GxsTunnels, since tunnels are shared between services.
// however,
DistantChatContact& contact(mDistantChatContacts[DistantChatPeerId(tunnel_id)]) ; DistantChatContact& contact(mDistantChatContacts[DistantChatPeerId(tunnel_id)]) ;
contact.to_id = tinfo.destination_gxs_id ; contact.to_id = tinfo.destination_gxs_id ;
contact.from_id = tinfo.source_gxs_id ; contact.from_id = tinfo.source_gxs_id ;
} }
RsItem *item = RsChatSerialiser().deserialise(data,&data_size) ;
if(item != NULL) if(item != NULL)
{ {
item->PeerId(RsPeerId(tunnel_id)) ; // just in case, but normally this is already done. item->PeerId(RsPeerId(tunnel_id)) ; // just in case, but normally this is already done.
handleIncomingItem(item) ; handleIncomingItem(item) ;
RsServer::notify()->notifyListChange(NOTIFY_LIST_PRIVATE_INCOMING_CHAT, NOTIFY_TYPE_ADD); RsServer::notify()->notifyListChange(NOTIFY_LIST_PRIVATE_INCOMING_CHAT, NOTIFY_TYPE_ADD);
} }
else else
std::cerr << " (EE) item could not be deserialised!" << std::endl; std::cerr << " (EE) item could not be deserialised!" << std::endl;
} }
void DistantChatService::markDistantChatAsClosed(const DistantChatPeerId& dcpid) void DistantChatService::markDistantChatAsClosed(const DistantChatPeerId& dcpid)
@ -243,4 +258,62 @@ bool DistantChatService::closeDistantChatConnexion(const DistantChatPeerId &tunn
return true ; return true ;
} }
uint32_t DistantChatService::getDistantChatPermissionFlags()
{
return mDistantChatPermissions ;
}
bool DistantChatService::setDistantChatPermissionFlags(uint32_t flags)
{
if(mDistantChatPermissions != flags)
{
mDistantChatPermissions = flags ;
std::cerr << "(II) Changing distant chat permissions to " << flags << ". Existing openned chats will however remain active until closed" << std::endl;
triggerConfigSave() ;
}
return true ;
}
void DistantChatService::addToSaveList(std::list<RsItem*>& list) const
{
/* Save permission flags */
RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ;
RsTlvKeyValue kv;
kv.key = "DISTANT_CHAT_PERMISSION_FLAGS" ;
kv.value = RsUtil::NumberToString(mDistantChatPermissions) ;
vitem->tlvkvs.pairs.push_back(kv) ;
list.push_back(vitem) ;
}
bool DistantChatService::processLoadListItem(const RsItem *item)
{
const RsConfigKeyValueSet *vitem = NULL ;
if(NULL != (vitem = dynamic_cast<const RsConfigKeyValueSet*>(item)))
for(std::list<RsTlvKeyValue>::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit)
if(kit->key == "DISTANT_CHAT_PERMISSION_FLAGS")
{
#ifdef DEBUG_DISTANT_CHAT
std::cerr << "Loaded distant chat permission flags: " << kit->value << std::endl ;
#endif
if (!kit->value.empty())
{
std::istringstream is(kit->value) ;
uint32_t tmp ;
is >> tmp ;
if(tmp < 3)
mDistantChatPermissions = tmp ;
else
std::cerr << "(EE) Invalid value read for DistantChatPermission flags in config: " << tmp << std::endl;
}
return true;
}
return false ;
}

View File

@ -42,18 +42,27 @@ public:
DistantChatService() : mDistantChatMtx("distant chat") DistantChatService() : mDistantChatMtx("distant chat")
{ {
mGxsTunnels = NULL ; mGxsTunnels = NULL ;
mDistantChatPermissions = RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NONE ; // default: accept everyone
} }
// Overloaded methods from RsGxsTunnelClientService virtual void triggerConfigSave()=0 ;
bool processLoadListItem(const RsItem *item) ;
void addToSaveList(std::list<RsItem*>& list) const;
virtual void connectToGxsTunnelService(RsGxsTunnelService *tunnel_service) ;
// Creates the invite if the public key of the distant peer is available. // Creates the invite if the public key of the distant peer is available.
// Om success, stores the invite in the map above, so that we can respond to tunnel requests. // Om success, stores the invite in the map above, so that we can respond to tunnel requests.
// //
bool initiateDistantChatConnexion(const RsGxsId& to_gxs_id, const RsGxsId &from_gxs_id, DistantChatPeerId& dcpid, uint32_t &error_code) ; bool initiateDistantChatConnexion(const RsGxsId& to_gxs_id, const RsGxsId &from_gxs_id, DistantChatPeerId& dcpid, uint32_t &error_code) ;
bool closeDistantChatConnexion(const DistantChatPeerId &tunnel_id) ; bool closeDistantChatConnexion(const DistantChatPeerId &tunnel_id) ;
// Sets flags to only allow connexion from some people.
uint32_t getDistantChatPermissionFlags() ;
bool setDistantChatPermissionFlags(uint32_t flags) ;
// Returns the status of a distant chat contact. The contact is defined by the tunnel id (turned into a DistantChatPeerId) because
// each pair of talking GXS id needs to be treated separately
virtual bool getDistantChatStatus(const DistantChatPeerId &tunnel_id, DistantChatPeerInfo& cinfo) ; virtual bool getDistantChatStatus(const DistantChatPeerId &tunnel_id, DistantChatPeerInfo& cinfo) ;
// derived in p3ChatService, so as to pass down some info // derived in p3ChatService, so as to pass down some info
@ -74,8 +83,17 @@ private:
// //
std::map<DistantChatPeerId, DistantChatContact> mDistantChatContacts ; // current peers we can talk to std::map<DistantChatPeerId, DistantChatContact> mDistantChatContacts ; // current peers we can talk to
// Permission handling
uint32_t mDistantChatPermissions ;
// Overloaded from RsGxsTunnelClientService // Overloaded from RsGxsTunnelClientService
public:
virtual void connectToGxsTunnelService(RsGxsTunnelService *tunnel_service) ;
private:
virtual bool acceptDataFromPeer(const RsGxsId& gxs_id) ;
virtual void notifyTunnelStatus(const RsGxsTunnelService::RsGxsTunnelId& tunnel_id,uint32_t tunnel_status) ; virtual void notifyTunnelStatus(const RsGxsTunnelService::RsGxsTunnelId& tunnel_id,uint32_t tunnel_status) ;
virtual void receiveData(const RsGxsTunnelService::RsGxsTunnelId& id,unsigned char *data,uint32_t data_size) ; virtual void receiveData(const RsGxsTunnelService::RsGxsTunnelId& id,unsigned char *data,uint32_t data_size) ;
@ -84,6 +102,5 @@ private:
void markDistantChatAsClosed(const DistantChatPeerId& dcpid) ; void markDistantChatAsClosed(const DistantChatPeerId& dcpid) ;
RsGxsTunnelService *mGxsTunnels ; RsGxsTunnelService *mGxsTunnels ;
RsMutex mDistantChatMtx ; RsMutex mDistantChatMtx ;
}; };

View File

@ -1903,19 +1903,19 @@ bool DistributedChatService::processLoadListItem(const RsItem *item)
if(NULL != (vitem = dynamic_cast<const RsConfigKeyValueSet*>(item))) if(NULL != (vitem = dynamic_cast<const RsConfigKeyValueSet*>(item)))
for(std::list<RsTlvKeyValue>::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) for(std::list<RsTlvKeyValue>::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit)
if(kit->key == "DEFAULT_IDENTITY") if(kit->key == "DEFAULT_IDENTITY")
{ {
#ifdef DEBUG_CHAT_LOBBIES #ifdef DEBUG_CHAT_LOBBIES
std::cerr << "Loaded config default nick name for distributed chat: " << kit->value << std::endl ; std::cerr << "Loaded config default nick name for distributed chat: " << kit->value << std::endl ;
#endif #endif
if (!kit->value.empty()) if (!kit->value.empty())
{ {
_default_identity = RsGxsId(kit->value) ; _default_identity = RsGxsId(kit->value) ;
if(_default_identity.isNull()) if(_default_identity.isNull())
std::cerr << "ERROR: default identity is malformed." << std::endl; std::cerr << "ERROR: default identity is malformed." << std::endl;
} }
return true; return true;
} }
const RsChatLobbyConfigItem *clci = NULL ; const RsChatLobbyConfigItem *clci = NULL ;

View File

@ -1192,11 +1192,8 @@ bool p3ChatService::loadList(std::list<RsItem*>& load)
continue; continue;
} }
if(DistributedChatService::processLoadListItem(*it)) DistributedChatService::processLoadListItem(*it) ;
{ DistantChatService::processLoadListItem(*it) ;
delete *it;
continue;
}
// delete unknown items // delete unknown items
delete *it; delete *it;
@ -1238,6 +1235,7 @@ bool p3ChatService::saveList(bool& cleanup, std::list<RsItem*>& list)
} }
DistributedChatService::addToSaveList(list) ; DistributedChatService::addToSaveList(list) ;
DistantChatService::addToSaveList(list) ;
return true; return true;
} }

View File

@ -53,186 +53,186 @@ typedef RsPeerId ChatLobbyVirtualPeerId ;
*/ */
class p3ChatService: public p3Service, public DistantChatService, public DistributedChatService, public p3Config, public pqiServiceMonitor class p3ChatService: public p3Service, public DistantChatService, public DistributedChatService, public p3Config, public pqiServiceMonitor
{ {
public: public:
p3ChatService(p3ServiceControl *cs, p3IdService *pids,p3LinkMgr *cm, p3HistoryMgr *historyMgr); p3ChatService(p3ServiceControl *cs, p3IdService *pids,p3LinkMgr *cm, p3HistoryMgr *historyMgr);
virtual RsServiceInfo getServiceInfo(); virtual RsServiceInfo getServiceInfo();
/***** overloaded from p3Service *****/ /***** overloaded from p3Service *****/
/*! /*!
* This retrieves all chat msg items and also (important!) * This retrieves all chat msg items and also (important!)
* processes chat-status items that are in service item queue. chat msg item requests are also processed and not returned * processes chat-status items that are in service item queue. chat msg item requests are also processed and not returned
* (important! also) notifications sent to notify base on receipt avatar, immediate status and custom status * (important! also) notifications sent to notify base on receipt avatar, immediate status and custom status
* : notifyCustomState, notifyChatStatus, notifyPeerHasNewAvatar * : notifyCustomState, notifyChatStatus, notifyPeerHasNewAvatar
* @see NotifyBase * @see NotifyBase
*/ */
virtual int tick(); virtual int tick();
/*************** pqiMonitor callback ***********************/ /*************** pqiMonitor callback ***********************/
virtual void statusChange(const std::list<pqiServicePeer> &plist); virtual void statusChange(const std::list<pqiServicePeer> &plist);
/*! /*!
* public chat sent to all peers * public chat sent to all peers
*/ */
void sendPublicChat(const std::string &msg); void sendPublicChat(const std::string &msg);
/********* RsMsgs ***********/ /********* RsMsgs ***********/
/*! /*!
* Send a chat message. * Send a chat message.
* @param destination where to send the chat message * @param destination where to send the chat message
* @param msg the message * @param msg the message
* @see ChatId * @see ChatId
*/ */
bool sendChat(ChatId destination, std::string msg); bool sendChat(ChatId destination, std::string msg);
/*! /*!
* chat is sent to specifc peer * chat is sent to specifc peer
* @param id peer to send chat msg to * @param id peer to send chat msg to
*/ */
bool sendPrivateChat(const RsPeerId &id, const std::string &msg); bool sendPrivateChat(const RsPeerId &id, const std::string &msg);
/*! /*!
* can be used to send 'immediate' status msgs, these status updates are meant for immediate use by peer (not saved by rs) * can be used to send 'immediate' status msgs, these status updates are meant for immediate use by peer (not saved by rs)
* e.g currently used to update user when a peer 'is typing' during a chat * e.g currently used to update user when a peer 'is typing' during a chat
*/ */
void sendStatusString(const ChatId& peer_id,const std::string& status_str) ; void sendStatusString(const ChatId& peer_id,const std::string& status_str) ;
/*! /*!
* send to all peers online * send to all peers online
*@see sendStatusString() *@see sendStatusString()
*/ */
void sendGroupChatStatusString(const std::string& status_str) ; void sendGroupChatStatusString(const std::string& status_str) ;
/*! /*!
* this retrieves custom status for a peers, generate a requests to the peer * this retrieves custom status for a peers, generate a requests to the peer
* @param peer_id the id of the peer you want status string for * @param peer_id the id of the peer you want status string for
*/ */
std::string getCustomStateString(const RsPeerId& peer_id) ; std::string getCustomStateString(const RsPeerId& peer_id) ;
/*! /*!
* sets the client's custom status, generates 'status available' item sent to all online peers * sets the client's custom status, generates 'status available' item sent to all online peers
*/ */
void setOwnCustomStateString(const std::string&) ; void setOwnCustomStateString(const std::string&) ;
/*! /*!
* @return client's custom string * @return client's custom string
*/ */
std::string getOwnCustomStateString() ; std::string getOwnCustomStateString() ;
/*! gets the peer's avatar in jpeg format, if available. Null otherwise. Also asks the peer to send /*! gets the peer's avatar in jpeg format, if available. Null otherwise. Also asks the peer to send
* its avatar, if not already available. Creates a new unsigned char array. It's the caller's * its avatar, if not already available. Creates a new unsigned char array. It's the caller's
* responsibility to delete this ones used. * responsibility to delete this ones used.
*/ */
void getAvatarJpegData(const RsPeerId& peer_id,unsigned char *& data,int& size) ; void getAvatarJpegData(const RsPeerId& peer_id,unsigned char *& data,int& size) ;
/*! /*!
* Sets the avatar data and size for client's account * Sets the avatar data and size for client's account
* @param data is copied, so should be destroyed by the caller * @param data is copied, so should be destroyed by the caller
*/ */
void setOwnAvatarJpegData(const unsigned char *data,int size) ; void setOwnAvatarJpegData(const unsigned char *data,int size) ;
/*! /*!
* Gets the avatar data for clients account * Gets the avatar data for clients account
* data is in jpeg format * data is in jpeg format
*/ */
void getOwnAvatarJpegData(unsigned char *& data,int& size) ; void getOwnAvatarJpegData(unsigned char *& data,int& size) ;
/*! /*!
* Return the max message size for security forwarding * Return the max message size for security forwarding
* @param type RS_CHAT_TYPE_... * @param type RS_CHAT_TYPE_...
* return 0 unlimited * return 0 unlimited
*/ */
static uint32_t getMaxMessageSecuritySize(int type); static uint32_t getMaxMessageSecuritySize(int type);
/*! /*!
* Checks message security, especially remove billion laughs attacks * Checks message security, especially remove billion laughs attacks
*/ */
static bool checkForMessageSecurity(RsChatMsgItem *) ; static bool checkForMessageSecurity(RsChatMsgItem *) ;
/*! /*!
* @param clear private chat queue * @param clear private chat queue
*/ */
bool clearPrivateChatQueue(bool incoming, const RsPeerId &id); bool clearPrivateChatQueue(bool incoming, const RsPeerId &id);
protected: protected:
/************* from p3Config *******************/ /************* from p3Config *******************/
virtual RsSerialiser *setupSerialiser() ; virtual RsSerialiser *setupSerialiser() ;
/*! /*!
* chat msg items and custom status are saved * chat msg items and custom status are saved
*/ */
virtual bool saveList(bool& cleanup, std::list<RsItem*>&) ; virtual bool saveList(bool& cleanup, std::list<RsItem*>&) ;
virtual void saveDone(); virtual void saveDone();
virtual bool loadList(std::list<RsItem*>& load) ; virtual bool loadList(std::list<RsItem*>& load) ;
// accepts virtual peer id // accepts virtual peer id
bool isOnline(const RsPeerId &pid) ; bool isOnline(const RsPeerId &pid) ;
/// This is to be used by subclasses/parents to call IndicateConfigChanged() /// This is to be used by subclasses/parents to call IndicateConfigChanged()
virtual void triggerConfigSave() { IndicateConfigChanged() ; } virtual void triggerConfigSave() { IndicateConfigChanged() ; }
/// Same, for storing messages in incoming list /// Same, for storing messages in incoming list
virtual void locked_storeIncomingMsg(RsChatMsgItem *) ; virtual void locked_storeIncomingMsg(RsChatMsgItem *) ;
private: private:
RsMutex mChatMtx; RsMutex mChatMtx;
class AvatarInfo ; class AvatarInfo ;
class StateStringInfo ; class StateStringInfo ;
// Receive chat queue // Receive chat queue
void receiveChatQueue(); void receiveChatQueue();
void handleIncomingItem(RsItem *); // called by the former, and turtle handler for incoming encrypted items void handleIncomingItem(RsItem *); // called by the former, and turtle handler for incoming encrypted items
virtual void sendChatItem(RsChatItem *) ; virtual void sendChatItem(RsChatItem *) ;
void initChatMessage(RsChatMsgItem *c, ChatMessage& msg); void initChatMessage(RsChatMsgItem *c, ChatMessage& msg);
/// Send avatar info to peer in jpeg format. /// Send avatar info to peer in jpeg format.
void sendAvatarJpegData(const RsPeerId& peer_id) ; void sendAvatarJpegData(const RsPeerId& peer_id) ;
/// Send custom state info to peer /// Send custom state info to peer
void sendCustomState(const RsPeerId& peer_id); void sendCustomState(const RsPeerId& peer_id);
/// Receive the avatar in a chat item, with RS_CHAT_RECEIVE_AVATAR flag. /// Receive the avatar in a chat item, with RS_CHAT_RECEIVE_AVATAR flag.
void receiveAvatarJpegData(RsChatAvatarItem *ci) ; // new method void receiveAvatarJpegData(RsChatAvatarItem *ci) ; // new method
void receiveStateString(const RsPeerId& id,const std::string& s) ; void receiveStateString(const RsPeerId& id,const std::string& s) ;
/// methods for handling various Chat items. /// methods for handling various Chat items.
bool handleRecvChatMsgItem(RsChatMsgItem *item) ; // returns false if the item should be deleted. bool handleRecvChatMsgItem(RsChatMsgItem *item) ; // returns false if the item should be deleted.
void handleRecvChatStatusItem(RsChatStatusItem *item) ; void handleRecvChatStatusItem(RsChatStatusItem *item) ;
void handleRecvChatAvatarItem(RsChatAvatarItem *item) ; void handleRecvChatAvatarItem(RsChatAvatarItem *item) ;
/// Sends a request for an avatar to the peer of given id /// Sends a request for an avatar to the peer of given id
void sendAvatarRequest(const RsPeerId& peer_id) ; void sendAvatarRequest(const RsPeerId& peer_id) ;
/// Send a request for custom status string /// Send a request for custom status string
void sendCustomStateRequest(const RsPeerId& peer_id); void sendCustomStateRequest(const RsPeerId& peer_id);
/// called as a proxy to sendItem(). Possibly splits item into multiple items of size lower than the maximum item size. /// called as a proxy to sendItem(). Possibly splits item into multiple items of size lower than the maximum item size.
//void checkSizeAndSendMessage(RsChatLobbyMsgItem *item) ; //void checkSizeAndSendMessage(RsChatLobbyMsgItem *item) ;
void checkSizeAndSendMessage(RsChatMsgItem *item) ; // keep for compatibility for a few weeks. void checkSizeAndSendMessage(RsChatMsgItem *item) ; // keep for compatibility for a few weeks.
/// Called when a RsChatMsgItem is received. The item may be collapsed with any waiting partial chat item from the same peer. /// Called when a RsChatMsgItem is received. The item may be collapsed with any waiting partial chat item from the same peer.
bool locked_checkAndRebuildPartialMessage(RsChatMsgItem *) ; bool locked_checkAndRebuildPartialMessage(RsChatMsgItem *) ;
RsChatAvatarItem *makeOwnAvatarItem() ; RsChatAvatarItem *makeOwnAvatarItem() ;
RsChatStatusItem *makeOwnCustomStateStringItem() ; RsChatStatusItem *makeOwnCustomStateStringItem() ;
p3ServiceControl *mServiceCtrl; p3ServiceControl *mServiceCtrl;
p3LinkMgr *mLinkMgr; p3LinkMgr *mLinkMgr;
p3HistoryMgr *mHistoryMgr; p3HistoryMgr *mHistoryMgr;
std::list<RsChatMsgItem *> privateOutgoingList; // messages waiting to be send when peer comes online std::list<RsChatMsgItem *> privateOutgoingList; // messages waiting to be send when peer comes online
AvatarInfo *_own_avatar ; AvatarInfo *_own_avatar ;
std::map<RsPeerId,AvatarInfo *> _avatars ; std::map<RsPeerId,AvatarInfo *> _avatars ;
std::map<RsPeerId,RsChatMsgItem *> _pendingPartialMessages ; std::map<RsPeerId,RsChatMsgItem *> _pendingPartialMessages ;
std::string _custom_status_string ; std::string _custom_status_string ;
std::map<RsPeerId,StateStringInfo> _state_strings ; std::map<RsPeerId,StateStringInfo> _state_strings ;
RsChatSerialiser *_serializer ; RsChatSerialiser *_serializer ;
}; };
class p3ChatService::StateStringInfo class p3ChatService::StateStringInfo

View File

@ -42,37 +42,41 @@ static const uint32_t GROUTER_CLIENT_SERVICE_DATA_STATUS_FAILED = 0x0002 ; //
class GRouterClientService class GRouterClientService
{ {
public: public:
// This method is called by the turtle router to send data that comes out of a turtle tunnel. // This method is called by the turtle router to send data that comes out of a turtle tunnel.
// The turtle router stays responsible for the memory management of data. Most of the time the // The turtle router stays responsible for the memory management of data. Most of the time the
// data chunk is a serialized item to be de-serialized by the client service. // data chunk is a serialized item to be de-serialized by the client service.
// //
// Parameters: // Parameters:
// item : global router item. Handled by the client service. // item : global router item. Handled by the client service.
// destination_key : key that is associated with this item. Can be useful for the client. // destination_key : key that is associated with this item. Can be useful for the client.
// //
// GRouter stays owner of the item, so the client should not delete it! // GRouter stays owner of the item, so the client should not delete it!
// //
virtual void receiveGRouterData(const RsGxsId& destination_key,const RsGxsId& /*signing_key*/, GRouterServiceId &/*client_id*/, uint8_t */*data*/, uint32_t /*data_size*/) virtual void receiveGRouterData(const RsGxsId& destination_key,const RsGxsId& /*signing_key*/, GRouterServiceId &/*client_id*/, uint8_t */*data*/, uint32_t /*data_size*/)
{ {
std::cerr << "!!!!!! Received Data from global router, but the client service is not handling it !!!!!!!!!!" << std::endl ; std::cerr << "!!!!!! Received Data from global router, but the client service is not handling it !!!!!!!!!!" << std::endl ;
std::cerr << " destination key_id = " << destination_key.toStdString() << std::endl; std::cerr << " destination key_id = " << destination_key.toStdString() << std::endl;
} }
// This method is called by the global router when a message has been received, or cannot be sent, etc. // This method is called by the global router when a message has been received, or cannot be sent, etc.
// //
virtual void notifyDataStatus(const GRouterMsgPropagationId& received_id,uint32_t data_status) virtual void notifyDataStatus(const GRouterMsgPropagationId& received_id,uint32_t data_status)
{ {
std::cerr << "!!!!!! Received Data status from global router, but the client service is not handling it !!!!!!!!!!" << std::endl ; std::cerr << "!!!!!! Received Data status from global router, but the client service is not handling it !!!!!!!!!!" << std::endl ;
std::cerr << " message ID = " << received_id << std::endl; std::cerr << " message ID = " << received_id << std::endl;
std::cerr << " data status = " << data_status << std::endl; std::cerr << " data status = " << data_status << std::endl;
} }
// This function is mandatory. It should do two things: // This function is mandatory. It should do two things:
// 1 - keep a pointer to the global router, so as to be able to send data (e.g. copy pt into a local variable) // 1 - keep a pointer to the global router, so as to be able to send data (e.g. copy pt into a local variable)
// 2 - call pt->registerTunnelService(this), so that the TR knows that service and can send back information to it. // 2 - call pt->registerTunnelService(this), so that the TR knows that service and can send back information to it.
// //
virtual void connectToGlobalRouter(p3GRouter *pt) = 0 ; virtual void connectToGlobalRouter(p3GRouter *pt) = 0 ;
// should be derived to determine wether the client accepts data from this peer or not. If not, the data is dropped.
virtual bool acceptDataFromPeer(const RsGxsId& gxs_id) =0;
}; };

View File

@ -1661,10 +1661,13 @@ void p3GRouter::handleIncomingDataItem(RsGRouterGenericDataItem *data_item)
std::cerr << " notyfying client." << std::endl; std::cerr << " notyfying client." << std::endl;
#endif #endif
client->receiveGRouterData(decrypted_item->destination_key,decrypted_item->signature.keyId,service_id,decrypted_item->data_bytes,decrypted_item->data_size); if(client->acceptDataFromPeer(decrypted_item->signature.keyId))
{
decrypted_item->data_bytes = NULL ; client->receiveGRouterData(decrypted_item->destination_key,decrypted_item->signature.keyId,service_id,decrypted_item->data_bytes,decrypted_item->data_size);
decrypted_item->data_size = 0 ;
decrypted_item->data_bytes = NULL ;
decrypted_item->data_size = 0 ;
}
delete decrypted_item ; delete decrypted_item ;
} }

View File

@ -327,6 +327,8 @@ void p3GxsTunnelService::handleRecvTunnelDataItem(const RsGxsTunnelId& tunnel_id
#endif #endif
RsGxsTunnelClientService *service = NULL ; RsGxsTunnelClientService *service = NULL ;
RsGxsId peer_from ;
{ {
RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/
std::map<uint32_t,RsGxsTunnelClientService *>::const_iterator it = mRegisteredServices.find(item->service_id) ; std::map<uint32_t,RsGxsTunnelClientService *>::const_iterator it = mRegisteredServices.find(item->service_id) ;
@ -341,10 +343,14 @@ void p3GxsTunnelService::handleRecvTunnelDataItem(const RsGxsTunnelId& tunnel_id
std::map<RsGxsTunnelId,GxsTunnelPeerInfo>::iterator it2 = _gxs_tunnel_contacts.find(tunnel_id) ; std::map<RsGxsTunnelId,GxsTunnelPeerInfo>::iterator it2 = _gxs_tunnel_contacts.find(tunnel_id) ;
if(it2 != _gxs_tunnel_contacts.end()) if(it2 != _gxs_tunnel_contacts.end())
{
it2->second.client_services.insert(item->service_id) ; it2->second.client_services.insert(item->service_id) ;
peer_from = it2->second.to_gxs_id ;
}
} }
service->receiveData(tunnel_id,item->data,item->data_size) ; if(service->acceptDataFromPeer(peer_from))
service->receiveData(tunnel_id,item->data,item->data_size) ;
item->data = NULL ; // avoids deletion, since the client has the memory now item->data = NULL ; // avoids deletion, since the client has the memory now
item->data_size = 0 ; item->data_size = 0 ;

View File

@ -63,6 +63,10 @@ public:
// Used by the creator of the service to supply a pointer to the GXS tunnel service for it to be able to send data etc. // Used by the creator of the service to supply a pointer to the GXS tunnel service for it to be able to send data etc.
virtual void connectToGxsTunnelService(RsGxsTunnelService *tunnel_service) =0; virtual void connectToGxsTunnelService(RsGxsTunnelService *tunnel_service) =0;
// Gives feedback about type of data that is allowed in. For security reasons, this always needs to be re-derived (Clients can return true on default)
virtual bool acceptDataFromPeer(const RsGxsId& gxs_id) = 0 ;
}; };
class GxsTunnelInfo class GxsTunnelInfo

View File

@ -250,6 +250,7 @@ virtual bool getRecognTagRequest(const RsGxsId &id, const std::string &comment,
uint16_t tag_class, uint16_t tag_type, std::string &tag) = 0; uint16_t tag_class, uint16_t tag_type, std::string &tag) = 0;
virtual bool setAsRegularContact(const RsGxsId& id,bool is_a_contact) = 0 ; virtual bool setAsRegularContact(const RsGxsId& id,bool is_a_contact) = 0 ;
virtual bool isARegularContact(const RsGxsId& id) = 0 ;
// Specific RsIdentity Functions.... // Specific RsIdentity Functions....
/* Specific Service Data */ /* Specific Service Data */

View File

@ -264,11 +264,11 @@ public:
#define RS_DISTANT_CHAT_FLAG_SIGNED 0x0001 #define RS_DISTANT_CHAT_FLAG_SIGNED 0x0001
#define RS_DISTANT_CHAT_FLAG_SIGNATURE_OK 0x0002 #define RS_DISTANT_CHAT_FLAG_SIGNATURE_OK 0x0002
// flags to define who we accept to talk to // flags to define who we accept to talk to. Each flag *removes* some people.
#define RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_NONE 0x0000 #define RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NONE 0x0000
#define RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_EVERYBODY 0x0001 #define RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NON_CONTACTS 0x0001
#define RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_CONTACT_LIST 0x0002 #define RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_EVERYBODY 0x0002
struct DistantChatPeerInfo struct DistantChatPeerInfo
{ {
@ -482,6 +482,9 @@ virtual ChatLobbyId createChatLobby(const std::string& lobby_name,const RsGxsId&
/* Distant chat */ /* Distant chat */
/****************************************/ /****************************************/
virtual uint32_t getDistantChatPermissionFlags()=0 ;
virtual bool setDistantChatPermissionFlags(uint32_t flags)=0 ;
virtual bool initiateDistantChatConnexion(const RsGxsId& to_pid,const RsGxsId& from_pid,DistantChatPeerId& pid,uint32_t& error_code) = 0; virtual bool initiateDistantChatConnexion(const RsGxsId& to_pid,const RsGxsId& from_pid,DistantChatPeerId& pid,uint32_t& error_code) = 0;
virtual bool getDistantChatStatus(const DistantChatPeerId& pid,DistantChatPeerInfo& info)=0; virtual bool getDistantChatStatus(const DistantChatPeerId& pid,DistantChatPeerInfo& info)=0;
virtual bool closeDistantChatConnexion(const DistantChatPeerId& pid)=0; virtual bool closeDistantChatConnexion(const DistantChatPeerId& pid)=0;

View File

@ -537,4 +537,12 @@ bool p3Msgs::closeDistantChatConnexion(const DistantChatPeerId &pid)
{ {
return mChatSrv->closeDistantChatConnexion(pid) ; return mChatSrv->closeDistantChatConnexion(pid) ;
} }
bool p3Msgs::setDistantChatPermissionFlags(uint32_t flags)
{
return mChatSrv->setDistantChatPermissionFlags(flags) ;
}
uint32_t p3Msgs::getDistantChatPermissionFlags()
{
return mChatSrv->getDistantChatPermissionFlags() ;
}

View File

@ -159,6 +159,9 @@ class p3Msgs: public RsMsgs
virtual bool getDistantChatStatus(const DistantChatPeerId& gxs_id,DistantChatPeerInfo& info); virtual bool getDistantChatStatus(const DistantChatPeerId& gxs_id,DistantChatPeerInfo& info);
virtual bool closeDistantChatConnexion(const DistantChatPeerId &pid) ; virtual bool closeDistantChatConnexion(const DistantChatPeerId &pid) ;
virtual uint32_t getDistantChatPermissionFlags() ;
virtual bool setDistantChatPermissionFlags(uint32_t flags) ;
private: private:
p3MsgService *mMsgSrv; p3MsgService *mMsgSrv;

View File

@ -212,6 +212,13 @@ uint32_t p3IdService::idAuthenPolicy()
return policy; return policy;
} }
bool p3IdService::isARegularContact(const RsGxsId& id)
{
RsStackMutex stack(mIdMtx);
return mContacts.find(id) != mContacts.end() ;
}
bool p3IdService::setAsRegularContact(const RsGxsId& id,bool b) bool p3IdService::setAsRegularContact(const RsGxsId& id,bool b)
{ {
std::set<RsGxsId>::iterator it = mContacts.find(id) ; std::set<RsGxsId>::iterator it = mContacts.find(id) ;

View File

@ -266,6 +266,7 @@ virtual bool getRecognTagRequest(const RsGxsId &id, const std::string &comment,
uint16_t tag_class, uint16_t tag_type, std::string &tag); uint16_t tag_class, uint16_t tag_type, std::string &tag);
virtual bool setAsRegularContact(const RsGxsId& id,bool is_a_contact) ; virtual bool setAsRegularContact(const RsGxsId& id,bool is_a_contact) ;
virtual bool isARegularContact(const RsGxsId& id) ;
/**************** RsGixs Implementation ***************/ /**************** RsGixs Implementation ***************/

View File

@ -87,6 +87,7 @@ p3MsgService::p3MsgService(p3ServiceControl *sc, p3IdService *id_serv)
mShouldEnableDistantMessaging = true ; mShouldEnableDistantMessaging = true ;
mDistantMessagingEnabled = false ; mDistantMessagingEnabled = false ;
mDistantMessagePermissions = RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NONE ;
/* Initialize standard tag types */ /* Initialize standard tag types */
if(sc) if(sc)
@ -468,6 +469,10 @@ bool p3MsgService::saveList(bool& cleanup, std::list<RsItem*>& itemList)
kv.key = "DISTANT_MESSAGES_ENABLED" ; kv.key = "DISTANT_MESSAGES_ENABLED" ;
kv.value = mShouldEnableDistantMessaging?"YES":"NO" ; kv.value = mShouldEnableDistantMessaging?"YES":"NO" ;
vitem->tlvkvs.pairs.push_back(kv) ; vitem->tlvkvs.pairs.push_back(kv) ;
kv.key = "DISTANT_MESSAGE_PERMISSION_FLAGS" ;
kv.value = RsUtil::NumberToString(mDistantMessagePermissions) ;
vitem->tlvkvs.pairs.push_back(kv) ;
itemList.push_back(vitem) ; itemList.push_back(vitem) ;
@ -558,13 +563,13 @@ bool p3MsgService::loadList(std::list<RsItem*>& load)
mMsgUniqueId = mitem->msgId + 1; mMsgUniqueId = mitem->msgId + 1;
} }
items.push_back(mitem); items.push_back(mitem);
} }
else if (NULL != (grm = dynamic_cast<RsMsgGRouterMap *>(*it))) else if (NULL != (grm = dynamic_cast<RsMsgGRouterMap *>(*it)))
{ {
// merge. // merge.
for(std::map<GRouterMsgPropagationId,uint32_t>::const_iterator it(grm->ongoing_msgs.begin());it!=grm->ongoing_msgs.end();++it) for(std::map<GRouterMsgPropagationId,uint32_t>::const_iterator it(grm->ongoing_msgs.begin());it!=grm->ongoing_msgs.end();++it)
_ongoing_messages.insert(*it) ; _ongoing_messages.insert(*it) ;
} }
else if(NULL != (mtt = dynamic_cast<RsMsgTagType *>(*it))) else if(NULL != (mtt = dynamic_cast<RsMsgTagType *>(*it)))
{ {
// delete standard tags as they are now save in config // delete standard tags as they are now save in config
@ -574,7 +579,7 @@ bool p3MsgService::loadList(std::list<RsItem*>& load)
} }
else else
{ {
delete mTags[mtt->tagId]; delete mTags[mtt->tagId];
mTags.erase(tagIt); mTags.erase(tagIt);
mTags.insert(std::pair<uint32_t, RsMsgTagType* >(mtt->tagId, mtt)); mTags.insert(std::pair<uint32_t, RsMsgTagType* >(mtt->tagId, mtt));
} }
@ -586,7 +591,7 @@ bool p3MsgService::loadList(std::list<RsItem*>& load)
} }
else if(NULL != (msi = dynamic_cast<RsMsgSrcId *>(*it))) else if(NULL != (msi = dynamic_cast<RsMsgSrcId *>(*it)))
{ {
srcIdMsgMap.insert(std::pair<uint32_t, RsPeerId>(msi->msgId, msi->srcId)); srcIdMsgMap.insert(std::pair<uint32_t, RsPeerId>(msi->msgId, msi->srcId));
mSrcIds.insert(std::pair<uint32_t, RsMsgSrcId*>(msi->msgId, msi)); // does not need to be kept mSrcIds.insert(std::pair<uint32_t, RsMsgSrcId*>(msi->msgId, msi)); // does not need to be kept
} }
else if(NULL != (msp = dynamic_cast<RsMsgParentId *>(*it))) else if(NULL != (msp = dynamic_cast<RsMsgParentId *>(*it)))
@ -598,13 +603,33 @@ bool p3MsgService::loadList(std::list<RsItem*>& load)
if(NULL != (vitem = dynamic_cast<RsConfigKeyValueSet*>(*it))) if(NULL != (vitem = dynamic_cast<RsConfigKeyValueSet*>(*it)))
for(std::list<RsTlvKeyValue>::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) for(std::list<RsTlvKeyValue>::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit)
if(kit->key == "DISTANT_MESSAGES_ENABLED") {
if(kit->key == "DISTANT_MESSAGES_ENABLED")
{ {
#ifdef MSG_DEBUG #ifdef MSG_DEBUG
std::cerr << "Loaded config default nick name for distant chat: " << kit->value << std::endl ; std::cerr << "Loaded config default nick name for distant chat: " << kit->value << std::endl ;
#endif #endif
mShouldEnableDistantMessaging = (kit->value == "YES") ; mShouldEnableDistantMessaging = (kit->value == "YES") ;
} }
if(kit->key == "DISTANT_MESSAGE_PERMISSION_FLAGS")
{
#ifdef MSG_DEBUG
std::cerr << "Loaded distant message permission flags: " << kit->value << std::endl ;
#endif
if (!kit->value.empty())
{
std::istringstream is(kit->value) ;
uint32_t tmp ;
is >> tmp ;
if(tmp < 3)
mDistantMessagePermissions = tmp ;
else
std::cerr << "(EE) Invalid value read for DistantMessagePermission flags in config: " << tmp << std::endl;
}
}
}
} }
@ -1791,6 +1816,32 @@ void p3MsgService::notifyDataStatus(const GRouterMsgPropagationId& id,uint32_t d
RsServer::notify()->notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_ADD); RsServer::notify()->notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_ADD);
IndicateConfigChanged() ; IndicateConfigChanged() ;
} }
bool p3MsgService::acceptDataFromPeer(const RsGxsId& to_gxs_id)
{
if(mDistantMessagePermissions & RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NON_CONTACTS)
return (rsIdentity!=NULL) && rsIdentity->isARegularContact(to_gxs_id) ;
if(mDistantMessagePermissions & RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_EVERYBODY)
return false ;
return true ;
}
void p3MsgService::setDistantMessagingPermissionFlags(uint32_t flags)
{
if(flags != mDistantMessagePermissions)
{
mDistantMessagePermissions = flags ;
IndicateConfigChanged() ;
}
}
uint32_t p3MsgService::getDistantMessagingPermissionFlags()
{
return mDistantMessagePermissions ;
}
void p3MsgService::receiveGRouterData(const RsGxsId& destination_key, const RsGxsId& signing_key,GRouterServiceId& client_id,uint8_t *data,uint32_t data_size) void p3MsgService::receiveGRouterData(const RsGxsId& destination_key, const RsGxsId& signing_key,GRouterServiceId& client_id,uint8_t *data,uint32_t data_size)
{ {
std::cerr << "p3MsgService::receiveGRouterData(): received message item of size " << data_size << ", for key " << destination_key << std::endl; std::cerr << "p3MsgService::receiveGRouterData(): received message item of size " << data_size << ", for key " << destination_key << std::endl;

View File

@ -126,8 +126,9 @@ class p3MsgService: public p3Service, public p3Config, public pqiServiceMonitor,
}; };
void enableDistantMessaging(bool b) ; void enableDistantMessaging(bool b) ;
bool distantMessagingEnabled() ; bool distantMessagingEnabled() ;
void setDistantMessagingPermissionFlags(uint32_t flags) {}
uint32_t getDistantMessagingPermissionFlags() { return 0 ;} void setDistantMessagingPermissionFlags(uint32_t flags) ;
uint32_t getDistantMessagingPermissionFlags() ;
private: private:
void sendDistantMsgItem(RsMsgItem *msgitem) ; void sendDistantMsgItem(RsMsgItem *msgitem) ;
@ -139,6 +140,7 @@ class p3MsgService: public p3Service, public p3Config, public pqiServiceMonitor,
// Overloaded from GRouterClientService // Overloaded from GRouterClientService
virtual bool acceptDataFromPeer(const RsGxsId& gxs_id) ;
virtual void receiveGRouterData(const RsGxsId& destination_key,const RsGxsId& signing_key, GRouterServiceId &client_id, uint8_t *data, uint32_t data_size) ; virtual void receiveGRouterData(const RsGxsId& destination_key,const RsGxsId& signing_key, GRouterServiceId &client_id, uint8_t *data, uint32_t data_size) ;
virtual void notifyDataStatus(const GRouterMsgPropagationId& msg_id,uint32_t data_status) ; virtual void notifyDataStatus(const GRouterMsgPropagationId& msg_id,uint32_t data_status) ;
@ -205,6 +207,7 @@ class p3MsgService: public p3Service, public p3Config, public pqiServiceMonitor,
std::string config_dir; std::string config_dir;
bool mDistantMessagingEnabled ; bool mDistantMessagingEnabled ;
uint32_t mDistantMessagePermissions ;
bool mShouldEnableDistantMessaging ; bool mShouldEnableDistantMessaging ;
}; };

View File

@ -27,6 +27,7 @@
#include "util/rsprint.h" #include "util/rsprint.h"
#include "util/rsstring.h" #include "util/rsstring.h"
#include <iomanip> #include <iomanip>
#include <sstream>
#include <openssl/sha.h> #include <openssl/sha.h>
#include <sys/time.h> #include <sys/time.h>
@ -35,6 +36,15 @@
#include <sys/timeb.h> #include <sys/timeb.h>
#endif #endif
std::string RsUtil::NumberToString(uint64_t n)
{
std::ostringstream os ;
os << n ;
os.flush() ;
return os.str();
}
std::string RsUtil::BinToHex(const std::string &bin) std::string RsUtil::BinToHex(const std::string &bin)
{ {
return BinToHex(bin.c_str(), bin.length()); return BinToHex(bin.c_str(), bin.length());

View File

@ -36,6 +36,7 @@ namespace RsUtil {
std::string BinToHex(const std::string &bin); std::string BinToHex(const std::string &bin);
std::string BinToHex(const char *arr, const uint32_t len); std::string BinToHex(const char *arr, const uint32_t len);
std::string BinToHex(const unsigned char *arr, const uint32_t len); std::string BinToHex(const unsigned char *arr, const uint32_t len);
std::string NumberToString(uint64_t n);
std::string HashId(const std::string &id, bool reverse = false); std::string HashId(const std::string &id, bool reverse = false);
//std::string AccurateTimeString(); //std::string AccurateTimeString();

View File

@ -64,13 +64,13 @@ void MessagePage::distantMsgsComboBoxChanged(int i)
{ {
switch(i) switch(i)
{ {
case 0: rsMail->setDistantMessagingPermissionFlags(RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_EVERYBODY |RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_CONTACT_LIST) ; case 0: rsMail->setDistantMessagingPermissionFlags(RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NONE) ;
break ; break ;
case 1: rsMail->setDistantMessagingPermissionFlags(RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_CONTACT_LIST) ; case 1: rsMail->setDistantMessagingPermissionFlags(RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NON_CONTACTS) ;
break ; break ;
case 2: rsMail->setDistantMessagingPermissionFlags(RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_NONE) ; case 2: rsMail->setDistantMessagingPermissionFlags(RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_EVERYBODY) ;
break ; break ;
@ -123,9 +123,9 @@ MessagePage::load()
uint32_t flags = rsMail->getDistantMessagingPermissionFlags() ; uint32_t flags = rsMail->getDistantMessagingPermissionFlags() ;
if(flags == (RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_CONTACT_LIST | RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_EVERYBODY)) if(flags & RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_EVERYBODY)
ui.comboBox->setCurrentIndex(2); ui.comboBox->setCurrentIndex(2);
else if(flags == RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_CONTACT_LIST) else if(flags & RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NON_CONTACTS)
ui.comboBox->setCurrentIndex(1); ui.comboBox->setCurrentIndex(1);
else else
ui.comboBox->setCurrentIndex(0); ui.comboBox->setCurrentIndex(0);