Merge branch 'master' into qmlapp_pex_alpha

This commit is contained in:
Gioacchino Mazzurco 2017-05-31 12:11:15 +02:00
commit 59b77da6a2
113 changed files with 6880 additions and 1675 deletions

View file

@ -97,6 +97,7 @@ install:
# Install toolchain # Install toolchain
#- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-toolchain mingw-w64-x86_64-toolchain" #Already installed #- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-toolchain mingw-w64-x86_64-toolchain" #Already installed
# Install other binutils # Install other binutils
- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-curl mingw-w64-x86_64-curl"
- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-miniupnpc mingw-w64-x86_64-miniupnpc" - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-miniupnpc mingw-w64-x86_64-miniupnpc"
- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-sqlite3 mingw-w64-x86_64-sqlite3" - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-sqlite3 mingw-w64-x86_64-sqlite3"
- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-speex mingw-w64-x86_64-speex" - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-speex mingw-w64-x86_64-speex"

View file

@ -266,7 +266,7 @@ libs/curl-$(CURL_VERSION): $(DOWNLOAD_PATH)/curl-$(CURL_VERSION).tar.gz
sqlcipher: libs/sqlcipher-$(SQLCIPHER_VERSION) sqlcipher: libs/sqlcipher-$(SQLCIPHER_VERSION)
$(DOWNLOAD_PATH)/tcl$(TCL_VERSION)-src.tar.gz: $(DOWNLOAD_PATH)/tcl$(TCL_VERSION)-src.tar.gz:
wget http://prdownloads.sourceforge.net/tcl/tcl$(TCL_VERSION)-src.tar.gz -O $(DOWNLOAD_PATH)/tcl$(TCL_VERSION)-src.tar.gz wget --no-check-certificate http://downloads.sourceforge.net/project/tcl/Tcl/$(TCL_VERSION)/tcl$(TCL_VERSION)-src.tar.gz -O $(DOWNLOAD_PATH)/tcl$(TCL_VERSION)-src.tar.gz
$(DOWNLOAD_PATH)/sqlcipher-$(SQLCIPHER_VERSION).tar.gz: $(DOWNLOAD_PATH)/sqlcipher-$(SQLCIPHER_VERSION).tar.gz:
wget --no-check-certificate https://github.com/sqlcipher/sqlcipher/archive/v$(SQLCIPHER_VERSION).tar.gz -O $(DOWNLOAD_PATH)/sqlcipher-$(SQLCIPHER_VERSION).tar.gz wget --no-check-certificate https://github.com/sqlcipher/sqlcipher/archive/v$(SQLCIPHER_VERSION).tar.gz -O $(DOWNLOAD_PATH)/sqlcipher-$(SQLCIPHER_VERSION).tar.gz

View file

@ -443,8 +443,10 @@ void RsControlModule::handleCreateLocation(Request &req, Response &resp)
} }
} }
if(hidden_port) if(hidden_port) {
RsInit::SetHiddenLocation(hidden_address, hidden_port); /// TODO add bob to webui
RsInit::SetHiddenLocation(hidden_address, hidden_port, false);
}
std::string ssl_password = RSRandom::random_alphaNumericString(RsInit::getSslPwdLen()) ; std::string ssl_password = RSRandom::random_alphaNumericString(RsInit::getSslPwdLen()) ;

View file

@ -349,7 +349,7 @@ bool p3ChatService::sendChat(ChatId destination, std::string msg)
uint32_t sz = _serializer->size(ci); uint32_t sz = _serializer->size(ci);
std::vector<uint8_t> data; data.resize(sz); std::vector<uint8_t> data; data.resize(sz);
_serializer->serialise(ci, &data[0], &sz); _serializer->serialise(ci, &data[0], &sz);
mGxsTransport.sendMail(tId, GxsTransSubServices::P3_CHAT_SERVICE, mGxsTransport.sendData(tId, GxsTransSubServices::P3_CHAT_SERVICE,
de.from, de.to, &data[0], sz); de.from, de.to, &data[0], sz);
} }
else else

View file

@ -44,7 +44,7 @@
//#define DEBUG_CHACHA20 //#define DEBUG_CHACHA20
#if OPENSSL_VERSION_NUMBER >= 0x010100000L #if OPENSSL_VERSION_NUMBER >= 0x010100000L && !defined(LIBRESSL_VERSION_NUMBER)
#define AEAD_chacha20_poly1305_openssl AEAD_chacha20_poly1305 #define AEAD_chacha20_poly1305_openssl AEAD_chacha20_poly1305
#else #else
#define AEAD_chacha20_poly1305_rs AEAD_chacha20_poly1305 #define AEAD_chacha20_poly1305_rs AEAD_chacha20_poly1305
@ -386,7 +386,7 @@ void chacha20_encrypt_rs(uint8_t key[32], uint32_t block_counter, uint8_t nonce[
} }
} }
#if OPENSSL_VERSION_NUMBER >= 0x010100000L #if OPENSSL_VERSION_NUMBER >= 0x010100000L && !defined(LIBRESSL_VERSION_NUMBER)
void chacha20_encrypt_openssl(uint8_t key[32], uint32_t block_counter, uint8_t nonce[12], uint8_t *data, uint32_t size) void chacha20_encrypt_openssl(uint8_t key[32], uint32_t block_counter, uint8_t nonce[12], uint8_t *data, uint32_t size)
{ {
EVP_CIPHER_CTX *ctx; EVP_CIPHER_CTX *ctx;
@ -577,7 +577,7 @@ bool AEAD_chacha20_poly1305_rs(uint8_t key[32], uint8_t nonce[12],uint8_t *data,
} }
} }
#if OPENSSL_VERSION_NUMBER >= 0x010100000L #if OPENSSL_VERSION_NUMBER >= 0x010100000L && !defined(LIBRESSL_VERSION_NUMBER)
#define errorOut {ret = false; goto out;} #define errorOut {ret = false; goto out;}
bool AEAD_chacha20_poly1305_openssl(uint8_t key[32], uint8_t nonce[12], uint8_t *data, uint32_t data_size, uint8_t *aad, uint32_t aad_size, uint8_t tag[16], bool encrypt_or_decrypt) bool AEAD_chacha20_poly1305_openssl(uint8_t key[32], uint8_t nonce[12], uint8_t *data, uint32_t data_size, uint8_t *aad, uint32_t aad_size, uint8_t tag[16], bool encrypt_or_decrypt)
@ -667,7 +667,7 @@ bool AEAD_chacha20_sha256(uint8_t key[32], uint8_t nonce[12],uint8_t *data,uint3
if(encrypt) if(encrypt)
{ {
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
chacha20_encrypt_rs(key,1,nonce,data,data_size); chacha20_encrypt_rs(key,1,nonce,data,data_size);
#else #else
chacha20_encrypt_openssl(key, 1, nonce, data, data_size); chacha20_encrypt_openssl(key, 1, nonce, data, data_size);
@ -676,7 +676,7 @@ bool AEAD_chacha20_sha256(uint8_t key[32], uint8_t nonce[12],uint8_t *data,uint3
uint8_t computed_tag[EVP_MAX_MD_SIZE]; uint8_t computed_tag[EVP_MAX_MD_SIZE];
unsigned int md_size ; unsigned int md_size ;
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
HMAC_CTX hmac_ctx ; HMAC_CTX hmac_ctx ;
HMAC_CTX_init(&hmac_ctx) ; HMAC_CTX_init(&hmac_ctx) ;
@ -709,7 +709,7 @@ bool AEAD_chacha20_sha256(uint8_t key[32], uint8_t nonce[12],uint8_t *data,uint3
uint8_t computed_tag[EVP_MAX_MD_SIZE]; uint8_t computed_tag[EVP_MAX_MD_SIZE];
unsigned int md_size ; unsigned int md_size ;
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
HMAC_CTX hmac_ctx ; HMAC_CTX hmac_ctx ;
HMAC_CTX_init(&hmac_ctx) ; HMAC_CTX_init(&hmac_ctx) ;
@ -733,7 +733,7 @@ bool AEAD_chacha20_sha256(uint8_t key[32], uint8_t nonce[12],uint8_t *data,uint3
// decrypt // decrypt
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
chacha20_encrypt_rs(key,1,nonce,data,data_size); chacha20_encrypt_rs(key,1,nonce,data,data_size);
#else #else
chacha20_encrypt_openssl(key, 1, nonce, data, data_size); chacha20_encrypt_openssl(key, 1, nonce, data, data_size);
@ -1396,7 +1396,7 @@ bool perform_tests()
std::cerr << " AEAD/poly1305 own encryption speed : " << SIZE / (1024.0*1024.0) / s.duration() << " MB/s" << std::endl; std::cerr << " AEAD/poly1305 own encryption speed : " << SIZE / (1024.0*1024.0) / s.duration() << " MB/s" << std::endl;
} }
#if OPENSSL_VERSION_NUMBER >= 0x010100000L #if OPENSSL_VERSION_NUMBER >= 0x010100000L && !defined(LIBRESSL_VERSION_NUMBER)
{ {
RsScopeTimer s("AEAD3") ; RsScopeTimer s("AEAD3") ;
AEAD_chacha20_poly1305_openssl(key,nonce,ten_megabyte_data,SIZE,aad,12,received_tag,true) ; AEAD_chacha20_poly1305_openssl(key,nonce,ten_megabyte_data,SIZE,aad,12,received_tag,true) ;

View file

@ -1624,11 +1624,18 @@ Sha1CheckSum p3GRouter::computeDataItemHash(RsGRouterGenericDataItem *data_item)
RsTemporaryMemory mem(total_size) ; RsTemporaryMemory mem(total_size) ;
uint32_t offset = 0 ; uint32_t offset = 0 ;
signature_serializer.serialise(data_item,mem,&total_size) ; uint32_t tmp_size = total_size ;
offset += signed_data_size ; signature_serializer.serialise(data_item,mem,&tmp_size) ;
if(tmp_size != signed_data_size)
std::cerr << "(EE) Some error occured in p3GRouter::computeDataItemHash(). Mismatched offset/data size" << std::endl;
offset += tmp_size ;
data_item->signature.SetTlv(mem, total_size,&offset) ; data_item->signature.SetTlv(mem, total_size,&offset) ;
if(offset != total_size)
std::cerr << "(EE) Some error occured in p3GRouter::computeDataItemHash(). Mismatched offset/data size" << std::endl;
return RsDirUtil::sha1sum(mem,total_size) ; return RsDirUtil::sha1sum(mem,total_size) ;
} }
@ -1983,7 +1990,7 @@ bool p3GRouter::signDataItem(RsGRouterAbstractMsgItem *item,const RsGxsId& signi
std::cerr << "Created signature for data hash: " << RsDirUtil::sha1sum(data,data_size) << " and key id=" << signing_id << std::endl; std::cerr << "Created signature for data hash: " << RsDirUtil::sha1sum(data,data_size) << " and key id=" << signing_id << std::endl;
//#endif //#endif
// Check signature // Check signature
RsIdentityUsage::UsageCode info; RsIdentityUsage::UsageCode info = RsIdentityUsage::GLOBAL_ROUTER_SIGNATURE_CREATION;
uint32_t error; uint32_t error;
if(verifySignedDataItem(item,info,error)) if(verifySignedDataItem(item,info,error))

View file

@ -41,7 +41,7 @@ static const uint32_t MULTI_ENCRYPTION_FORMAT_v001_ENCRYPTED_KEY_SIZE = 256 ;
static RsGxsId getRsaKeyFingerprint_old_insecure_method(RSA *pubkey) static RsGxsId getRsaKeyFingerprint_old_insecure_method(RSA *pubkey)
{ {
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
int lenn = BN_num_bytes(pubkey -> n); int lenn = BN_num_bytes(pubkey -> n);
RsTemporaryMemory tmp(lenn) ; RsTemporaryMemory tmp(lenn) ;
@ -65,7 +65,7 @@ static RsGxsId getRsaKeyFingerprint_old_insecure_method(RSA *pubkey)
} }
static RsGxsId getRsaKeyFingerprint(RSA *pubkey) static RsGxsId getRsaKeyFingerprint(RSA *pubkey)
{ {
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
int lenn = BN_num_bytes(pubkey -> n); int lenn = BN_num_bytes(pubkey -> n);
int lene = BN_num_bytes(pubkey -> e); int lene = BN_num_bytes(pubkey -> e);
@ -359,7 +359,7 @@ bool GxsSecurity::getSignature(const char *data, uint32_t data_len, const RsTlvP
ok &= EVP_SignUpdate(mdctx, data, data_len) == 1; ok &= EVP_SignUpdate(mdctx, data, data_len) == 1;
unsigned int siglen = EVP_PKEY_size(key_priv); unsigned int siglen = EVP_PKEY_size(key_priv);
unsigned char sigbuf[siglen]; unsigned char sigbuf[siglen] = { 0 };
ok &= EVP_SignFinal(mdctx, sigbuf, &siglen, key_priv) == 1; ok &= EVP_SignFinal(mdctx, sigbuf, &siglen, key_priv) == 1;
// clean up // clean up

View file

@ -1576,11 +1576,20 @@ bool RsGxsDataAccess::getGroupStatistic(GroupStatisticRequest *req)
req->mGroupStatistic.mNumChildMsgsNew = 0; req->mGroupStatistic.mNumChildMsgsNew = 0;
req->mGroupStatistic.mNumChildMsgsUnread = 0; req->mGroupStatistic.mNumChildMsgsUnread = 0;
std::set<RsGxsMessageId> obsolete_msgs ; // stored message ids that are referred to as older versions of an existing message
for(uint32_t i = 0; i < msgMetaV.size(); ++i)
if(!msgMetaV[i]->mOrigMsgId.isNull() && msgMetaV[i]->mOrigMsgId!=msgMetaV[i]->mMsgId)
obsolete_msgs.insert(msgMetaV[i]->mOrigMsgId);
for(uint32_t i = 0; i < msgMetaV.size(); ++i) for(uint32_t i = 0; i < msgMetaV.size(); ++i)
{ {
RsGxsMsgMetaData* m = msgMetaV[i]; RsGxsMsgMetaData* m = msgMetaV[i];
req->mGroupStatistic.mTotalSizeOfMsgs += m->mMsgSize + m->serial_size(); req->mGroupStatistic.mTotalSizeOfMsgs += m->mMsgSize + m->serial_size();
if(obsolete_msgs.find(m->mMsgId) != obsolete_msgs.end()) // skip obsolete messages.
continue;
if (IS_MSG_NEW(m->mMsgStatus)) if (IS_MSG_NEW(m->mMsgStatus))
{ {
if (m->mParentId.isNull()) if (m->mParentId.isNull())

View file

@ -16,11 +16,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "util/rsdir.h"
#include "gxstrans/p3gxstrans.h" #include "gxstrans/p3gxstrans.h"
#include "util/stacktrace.h" #include "util/stacktrace.h"
typedef unsigned int uint; typedef unsigned int uint;
RsGxsTrans *rsGxsTrans = NULL ;
p3GxsTrans::~p3GxsTrans() p3GxsTrans::~p3GxsTrans()
{ {
p3Config::saveConfiguration(); p3Config::saveConfiguration();
@ -31,7 +34,36 @@ p3GxsTrans::~p3GxsTrans()
} }
} }
bool p3GxsTrans::sendMail( RsGxsTransId& mailId, bool p3GxsTrans::getStatistics(GxsTransStatistics& stats)
{
stats.prefered_group_id = mPreferredGroupId;
stats.outgoing_records.clear();
{
RS_STACK_MUTEX(mOutgoingMutex);
for ( auto it = mOutgoingQueue.begin(); it != mOutgoingQueue.end(); ++it)
{
const OutgoingRecord& pr(it->second);
RsGxsTransOutgoingRecord rec ;
rec.status = pr.status ;
rec.send_TS = pr.mailItem.meta.mPublishTs ;
rec.group_id = pr.mailItem.meta.mGroupId ;
rec.trans_id = pr.mailItem.mailId ;
rec.recipient = pr.recipient ;
rec.data_size = pr.mailData.size();
rec.data_hash = RsDirUtil::sha1sum(pr.mailData.data(),pr.mailData.size());
rec.client_service = pr.clientService ;
stats.outgoing_records.push_back(rec) ;
}
}
return true;
}
bool p3GxsTrans::sendData( RsGxsTransId& mailId,
GxsTransSubServices service, GxsTransSubServices service,
const RsGxsId& own_gxsid, const RsGxsId& recipient, const RsGxsId& own_gxsid, const RsGxsId& recipient,
const uint8_t* data, uint32_t size, const uint8_t* data, uint32_t size,
@ -55,7 +87,10 @@ bool p3GxsTrans::sendMail( RsGxsTransId& mailId,
} }
OutgoingRecord pr( recipient, service, data, size ); OutgoingRecord pr( recipient, service, data, size );
pr.mailItem.clear();
pr.mailItem.meta.mAuthorId = own_gxsid; pr.mailItem.meta.mAuthorId = own_gxsid;
pr.mailItem.meta.mMsgId.clear();
pr.mailItem.cryptoType = cm; pr.mailItem.cryptoType = cm;
pr.mailItem.mailId = RSRandom::random_u64(); pr.mailItem.mailId = RSRandom::random_u64();
@ -120,9 +155,9 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type)
&& meta.mGroupId != mPreferredGroupId; && meta.mGroupId != mPreferredGroupId;
if(shoudlSubscribe) if(shoudlSubscribe)
subscribeToGroup(token, meta.mGroupId, true); RsGenExchange::subscribeToGroup(token, meta.mGroupId, true);
else if(shoudlUnSubscribe) else if(shoudlUnSubscribe)
subscribeToGroup(token, meta.mGroupId, false); RsGenExchange::subscribeToGroup(token, meta.mGroupId, false);
#ifdef GXS_MAIL_GRP_DEBUG #ifdef GXS_MAIL_GRP_DEBUG
char buff[30]; char buff[30];
@ -220,10 +255,113 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type)
} }
} }
void p3GxsTrans::GxsTransIntegrityCleanupThread::run()
{
// first take out all the groups
std::map<RsGxsGroupId, RsNxsGrp*> grp;
mDs->retrieveNxsGrps(grp, true, true);
std::cerr << "GxsTransIntegrityCleanupThread::run()" << std::endl;
// compute hash and compare to stored value, if it fails then simply add it
// to list
GxsMsgReq grps;
for(std::map<RsGxsGroupId, RsNxsGrp*>::iterator git = grp.begin(); git != grp.end(); ++git)
{
RsNxsGrp* grp = git->second;
// store the group for retrieveNxsMsgs
grps[grp->grpId];
delete grp;
}
// now messages
std::map<RsGxsTransId,std::pair<RsGxsGroupId,RsGxsMessageId> > stored_msgs ;
std::list<RsGxsTransId> received_msgs ;
GxsMsgResult msgs;
mDs->retrieveNxsMsgs(grps, msgs, false, true);
for(GxsMsgResult::iterator mit = msgs.begin();mit != msgs.end(); ++mit)
{
std::vector<RsNxsMsg*>& msgV = mit->second;
std::vector<RsNxsMsg*>::iterator vit = msgV.begin();
for(; vit != msgV.end(); ++vit)
{
RsNxsMsg* msg = *vit;
RsGxsTransSerializer s ;
uint32_t size = msg->msg.bin_len;
RsItem *item = s.deserialise(msg->msg.bin_data,&size);
RsGxsTransMailItem *mitem ;
RsGxsTransPresignedReceipt *pitem ;
if(item == NULL)
std::cerr << " Unrecocognised item type!" << std::endl;
else if(NULL != (mitem = dynamic_cast<RsGxsTransMailItem*>(item)))
{
std::cerr << " " << msg->metaData->mMsgId << ": Mail data with ID " << std::hex << mitem->mailId << std::dec << " from " << msg->metaData->mAuthorId << " size: " << msg->msg.bin_len << std::endl;
stored_msgs[mitem->mailId] = std::make_pair(msg->metaData->mGroupId,msg->metaData->mMsgId) ;
}
else if(NULL != (pitem = dynamic_cast<RsGxsTransPresignedReceipt*>(item)))
{
std::cerr << " " << msg->metaData->mMsgId << ": Signed rcpt of ID " << std::hex << pitem->mailId << std::dec << " from " << msg->metaData->mAuthorId << " size: " << msg->msg.bin_len << std::endl;
received_msgs.push_back(pitem->mailId) ;
}
else
std::cerr << " Unknown item type!" << std::endl;
delete msg;
}
}
GxsMsgReq msgsToDel ;
std::cerr << "Msg removal report:" << std::endl;
for(std::list<RsGxsTransId>::const_iterator it(received_msgs.begin());it!=received_msgs.end();++it)
{
std::map<RsGxsTransId,std::pair<RsGxsGroupId,RsGxsMessageId> >::const_iterator it2 = stored_msgs.find(*it) ;
if(stored_msgs.end() != it2)
{
msgsToDel[it2->second.first].push_back(it2->second.second);
std::cerr << " scheduling msg " << std::hex << it2->second.first << "," << it2->second.second << " for deletion." << std::endl;
}
}
mDs->removeMsgs(msgsToDel);
}
void p3GxsTrans::service_tick() void p3GxsTrans::service_tick()
{ {
GxsTokenQueue::checkRequests(); GxsTokenQueue::checkRequests();
time_t now = time(NULL);
if(mLastMsgCleanup + MAX_DELAY_BETWEEN_CLEANUPS < now)
{
if(!mCleanupThread)
mCleanupThread = new GxsTransIntegrityCleanupThread(getDataStore());
if(mCleanupThread->isRunning())
std::cerr << "Cleanup thread is already running. Not running it again!" << std::endl;
else
{
std::cerr << "Starting GxsIntegrity cleanup thread." << std::endl;
mCleanupThread->start() ;
mLastMsgCleanup = now ;
}
}
{ {
RS_STACK_MUTEX(mOutgoingMutex); RS_STACK_MUTEX(mOutgoingMutex);
for ( auto it = mOutgoingQueue.begin(); it != mOutgoingQueue.end(); ) for ( auto it = mOutgoingQueue.begin(); it != mOutgoingQueue.end(); )
@ -337,7 +475,7 @@ void p3GxsTrans::notifyChanges(std::vector<RsGxsNotify*>& changes)
std::cout << "p3GxsTrans::notifyChanges(...) msgChange" << std::endl; std::cout << "p3GxsTrans::notifyChanges(...) msgChange" << std::endl;
uint32_t token; uint32_t token;
RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
getTokenService()->requestMsgInfo( token, 0xcaca, RsGenExchange::getTokenService()->requestMsgInfo( token, 0xcaca,
opts, msgChange->msgChangeMap ); opts, msgChange->msgChangeMap );
GxsTokenQueue::queueRequest(token, MAILS_UPDATE); GxsTokenQueue::queueRequest(token, MAILS_UPDATE);
@ -393,8 +531,8 @@ bool p3GxsTrans::requestGroupsData(const std::list<RsGxsGroupId>* groupIds)
// std::cout << "p3GxsTrans::requestGroupsList()" << std::endl; // std::cout << "p3GxsTrans::requestGroupsList()" << std::endl;
uint32_t token; uint32_t token;
RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
if(!groupIds) getTokenService()->requestGroupInfo(token, 0xcaca, opts); if(!groupIds) RsGenExchange::getTokenService()->requestGroupInfo(token, 0xcaca, opts);
else getTokenService()->requestGroupInfo(token, 0xcaca, opts, *groupIds); else RsGenExchange::getTokenService()->requestGroupInfo(token, 0xcaca, opts, *groupIds);
GxsTokenQueue::queueRequest(token, GROUPS_LIST); GxsTokenQueue::queueRequest(token, GROUPS_LIST);
return true; return true;
} }
@ -526,6 +664,7 @@ void p3GxsTrans::processOutgoingRecord(OutgoingRecord& pr)
{ {
pr.mailItem.saltRecipientHint(pr.recipient); pr.mailItem.saltRecipientHint(pr.recipient);
pr.mailItem.saltRecipientHint(RsGxsId::random()); pr.mailItem.saltRecipientHint(RsGxsId::random());
pr.mailItem.meta.mPublishTs = time(NULL);
} }
case GxsTransSendStatus::PENDING_PREFERRED_GROUP: case GxsTransSendStatus::PENDING_PREFERRED_GROUP:
{ {
@ -608,8 +747,7 @@ void p3GxsTrans::processOutgoingRecord(OutgoingRecord& pr)
pr.recipient, encryptError, true ) ) pr.recipient, encryptError, true ) )
{ {
pr.mailItem.payload.resize(encryptedSize); pr.mailItem.payload.resize(encryptedSize);
memcpy( &pr.mailItem.payload[0], encryptedData, memcpy( &pr.mailItem.payload[0], encryptedData, encryptedSize );
encryptedSize );
free(encryptedData); free(encryptedData);
break; break;
} }

View file

@ -26,6 +26,7 @@
#include "gxstrans/p3gxstransitems.h" #include "gxstrans/p3gxstransitems.h"
#include "services/p3idservice.h" // For p3IdService #include "services/p3idservice.h" // For p3IdService
#include "util/rsthreads.h" #include "util/rsthreads.h"
#include "retroshare/rsgxstrans.h"
struct p3GxsTrans; struct p3GxsTrans;
@ -76,18 +77,36 @@ struct GxsTransClient
* @see GxsTransClient::receiveGxsTransMail(...), * @see GxsTransClient::receiveGxsTransMail(...),
* @see GxsTransClient::notifyGxsTransSendStatus(...). * @see GxsTransClient::notifyGxsTransSendStatus(...).
*/ */
struct p3GxsTrans : RsGenExchange, GxsTokenQueue, p3Config class p3GxsTrans : public RsGenExchange, public GxsTokenQueue, public p3Config, public RsGxsTrans
{ {
public:
p3GxsTrans( RsGeneralDataService* gds, RsNetworkExchangeService* nes, p3GxsTrans( RsGeneralDataService* gds, RsNetworkExchangeService* nes,
p3IdService& identities ) : p3IdService& identities ) :
RsGenExchange( gds, nes, new RsGxsTransSerializer(), RsGenExchange( gds, nes, new RsGxsTransSerializer(),
RS_SERVICE_TYPE_GXS_TRANS, &identities, RS_SERVICE_TYPE_GXS_TRANS, &identities,
AuthenPolicy(), GXS_STORAGE_PERIOD ), AuthenPolicy(), GXS_STORAGE_PERIOD ),
GxsTokenQueue(this), mIdService(identities), GxsTokenQueue(this),
RsGxsTrans(this),
mIdService(identities),
mServClientsMutex("p3GxsTrans client services map mutex"), mServClientsMutex("p3GxsTrans client services map mutex"),
mOutgoingMutex("p3GxsTrans outgoing queue map mutex"), mOutgoingMutex("p3GxsTrans outgoing queue map mutex"),
mIngoingMutex("p3GxsTrans ingoing queue map mutex") {} mIngoingMutex("p3GxsTrans ingoing queue map mutex")
~p3GxsTrans(); {
mLastMsgCleanup = time(NULL) - 60; // to be changed into 0
mCleanupThread = NULL ;
}
virtual ~p3GxsTrans();
/*!
* \brief getStatistics
* Gathers all sorts of statistics about the internals of p3GxsTrans, in order to display info about the running status,
* message transport, etc.
* \param stats This structure contains all statistics information.
* \return true is the call succeeds.
*/
virtual bool getStatistics(GxsTransStatistics& stats);
/** /**
* Send an email to recipient, in the process author of the email is * Send an email to recipient, in the process author of the email is
@ -97,7 +116,7 @@ struct p3GxsTrans : RsGenExchange, GxsTokenQueue, p3Config
* This method is part of the public interface of this service. * This method is part of the public interface of this service.
* @return true if the mail will be sent, false if not * @return true if the mail will be sent, false if not
*/ */
bool sendMail( RsGxsTransId& mailId, bool sendData( RsGxsTransId& mailId,
GxsTransSubServices service, GxsTransSubServices service,
const RsGxsId& own_gxsid, const RsGxsId& recipient, const RsGxsId& own_gxsid, const RsGxsId& recipient,
const uint8_t* data, uint32_t size, const uint8_t* data, uint32_t size,
@ -139,7 +158,10 @@ private:
* signed acknowledged is received for each of them. * signed acknowledged is received for each of them.
* Two weeks seems fair ATM. * Two weeks seems fair ATM.
*/ */
const static uint32_t GXS_STORAGE_PERIOD = 0x127500; static const uint32_t GXS_STORAGE_PERIOD = 0x127500;
static const uint32_t MAX_DELAY_BETWEEN_CLEANUPS = 1203; // every 20 mins. Could be less.
time_t mLastMsgCleanup ;
/// Define how the backend should handle authentication based on signatures /// Define how the backend should handle authentication based on signatures
static uint32_t AuthenPolicy(); static uint32_t AuthenPolicy();
@ -251,5 +273,27 @@ private:
uint32_t decrypted_data_size ); uint32_t decrypted_data_size );
void notifyClientService(const OutgoingRecord& pr); void notifyClientService(const OutgoingRecord& pr);
/*!
* Checks the integrity message and groups
*/
class GxsTransIntegrityCleanupThread : public RsSingleJobThread
{
enum CheckState { CheckStart, CheckChecking };
public:
GxsTransIntegrityCleanupThread(RsGeneralDataService *const dataService): mDs(dataService) {}
bool isDone();
void run();
void getDeletedIds(std::list<RsGxsGroupId>& grpIds, std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >& msgIds);
private:
RsGeneralDataService* const mDs;
};
GxsTransIntegrityCleanupThread *mCleanupThread ;
}; };

View file

@ -23,41 +23,28 @@
#include "serialiser/rsbaseserial.h" #include "serialiser/rsbaseserial.h"
#include "serialiser/rstlvidset.h" #include "serialiser/rstlvidset.h"
#include "retroshare/rsgxsflags.h" #include "retroshare/rsgxsflags.h"
#include "retroshare/rsgxstrans.h"
#include "retroshare/rsgxscircles.h" // For: GXS_CIRCLE_TYPE_PUBLIC #include "retroshare/rsgxscircles.h" // For: GXS_CIRCLE_TYPE_PUBLIC
#include "services/p3idservice.h" #include "services/p3idservice.h"
#include "serialiser/rstypeserializer.h" #include "serialiser/rstypeserializer.h"
/// Subservices identifiers (like port for TCP) class RsNxsTransPresignedReceipt : public RsNxsMsg
enum class GxsTransSubServices : uint16_t
{
UNKNOWN = 0,
TEST_SERVICE = 1,
P3_MSG_SERVICE = 2,
P3_CHAT_SERVICE = 3
};
/// Values must fit into uint8_t
enum class GxsTransItemsSubtypes : uint8_t
{
GXS_TRANS_SUBTYPE_MAIL = 1,
GXS_TRANS_SUBTYPE_RECEIPT = 2,
GXS_TRANS_SUBTYPE_GROUP = 3,
OUTGOING_RECORD_ITEM = 4
};
typedef uint64_t RsGxsTransId;
struct RsNxsTransPresignedReceipt : RsNxsMsg
{ {
public:
RsNxsTransPresignedReceipt() : RsNxsMsg(RS_SERVICE_TYPE_GXS_TRANS) {} RsNxsTransPresignedReceipt() : RsNxsMsg(RS_SERVICE_TYPE_GXS_TRANS) {}
virtual ~RsNxsTransPresignedReceipt() {}
}; };
struct RsGxsTransBaseItem : RsGxsMsgItem class RsGxsTransBaseItem : public RsGxsMsgItem
{ {
public:
RsGxsTransBaseItem(GxsTransItemsSubtypes subtype) : RsGxsTransBaseItem(GxsTransItemsSubtypes subtype) :
RsGxsMsgItem( RS_SERVICE_TYPE_GXS_TRANS, RsGxsMsgItem( RS_SERVICE_TYPE_GXS_TRANS,
static_cast<uint8_t>(subtype) ), mailId(0) {} static_cast<uint8_t>(subtype) ), mailId(0) {}
virtual ~RsGxsTransBaseItem() {}
RsGxsTransId mailId; RsGxsTransId mailId;
void inline clear() void inline clear()
@ -71,10 +58,11 @@ struct RsGxsTransBaseItem : RsGxsMsgItem
{ RS_REGISTER_SERIAL_MEMBER_TYPED(mailId, uint64_t); } { RS_REGISTER_SERIAL_MEMBER_TYPED(mailId, uint64_t); }
}; };
struct RsGxsTransPresignedReceipt : RsGxsTransBaseItem class RsGxsTransPresignedReceipt : public RsGxsTransBaseItem
{ {
RsGxsTransPresignedReceipt() : public:
RsGxsTransBaseItem(GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT) {} RsGxsTransPresignedReceipt() : RsGxsTransBaseItem(GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT) {}
virtual ~RsGxsTransPresignedReceipt() {}
}; };
enum class RsGxsTransEncryptionMode : uint8_t enum class RsGxsTransEncryptionMode : uint8_t
@ -84,12 +72,15 @@ enum class RsGxsTransEncryptionMode : uint8_t
UNDEFINED_ENCRYPTION = 250 UNDEFINED_ENCRYPTION = 250
}; };
struct RsGxsTransMailItem : RsGxsTransBaseItem class RsGxsTransMailItem : public RsGxsTransBaseItem
{ {
public:
RsGxsTransMailItem() : RsGxsTransMailItem() :
RsGxsTransBaseItem(GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL), RsGxsTransBaseItem(GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL),
cryptoType(RsGxsTransEncryptionMode::UNDEFINED_ENCRYPTION) {} cryptoType(RsGxsTransEncryptionMode::UNDEFINED_ENCRYPTION) {}
virtual ~RsGxsTransMailItem() {}
RsGxsTransEncryptionMode cryptoType; RsGxsTransEncryptionMode cryptoType;
/** /**
@ -166,8 +157,9 @@ struct RsGxsTransMailItem : RsGxsTransBaseItem
const static uint32_t MAX_SIZE = 10*8*1024*1024; const static uint32_t MAX_SIZE = 10*8*1024*1024;
}; };
struct RsGxsTransGroupItem : RsGxsGrpItem class RsGxsTransGroupItem : public RsGxsGrpItem
{ {
public:
RsGxsTransGroupItem() : RsGxsTransGroupItem() :
RsGxsGrpItem( RS_SERVICE_TYPE_GXS_TRANS, RsGxsGrpItem( RS_SERVICE_TYPE_GXS_TRANS,
static_cast<uint8_t>( static_cast<uint8_t>(
@ -177,6 +169,7 @@ struct RsGxsTransGroupItem : RsGxsGrpItem
meta.mGroupName = "Mail"; meta.mGroupName = "Mail";
meta.mCircleType = GXS_CIRCLE_TYPE_PUBLIC; meta.mCircleType = GXS_CIRCLE_TYPE_PUBLIC;
} }
virtual ~RsGxsTransGroupItem() {}
// TODO: Talk with Cyril why there is no RsGxsGrpItem::serial_process // TODO: Talk with Cyril why there is no RsGxsGrpItem::serial_process
virtual void serial_process(RsGenericSerializer::SerializeJob /*j*/, virtual void serial_process(RsGenericSerializer::SerializeJob /*j*/,
@ -188,33 +181,16 @@ struct RsGxsTransGroupItem : RsGxsGrpItem
{ return out; } { return out; }
}; };
enum class GxsTransSendStatus : uint8_t
{
UNKNOWN = 0,
PENDING_PROCESSING,
PENDING_PREFERRED_GROUP,
PENDING_RECEIPT_CREATE,
PENDING_RECEIPT_SIGNATURE,
PENDING_SERIALIZATION,
PENDING_PAYLOAD_CREATE,
PENDING_PAYLOAD_ENCRYPT,
PENDING_PUBLISH,
/** This will be useful so the user can know if the mail reached at least
* some friend node, in case of internet connection interruption */
//PENDING_TRANSFER,
PENDING_RECEIPT_RECEIVE,
/// Records with status >= RECEIPT_RECEIVED get deleted
RECEIPT_RECEIVED,
FAILED_RECEIPT_SIGNATURE = 240,
FAILED_ENCRYPTION
};
class RsGxsTransSerializer; class RsGxsTransSerializer;
struct OutgoingRecord : RsItem
class OutgoingRecord : public RsItem
{ {
public:
OutgoingRecord( RsGxsId rec, GxsTransSubServices cs, OutgoingRecord( RsGxsId rec, GxsTransSubServices cs,
const uint8_t* data, uint32_t size ); const uint8_t* data, uint32_t size );
virtual ~OutgoingRecord() {}
GxsTransSendStatus status; GxsTransSendStatus status;
RsGxsId recipient; RsGxsId recipient;
/// Don't use a pointer would be invalid after publish /// Don't use a pointer would be invalid after publish
@ -234,10 +210,11 @@ private:
}; };
struct RsGxsTransSerializer : public RsServiceSerializer class RsGxsTransSerializer : public RsServiceSerializer
{ {
public:
RsGxsTransSerializer() : RsServiceSerializer(RS_SERVICE_TYPE_GXS_TRANS) {} RsGxsTransSerializer() : RsServiceSerializer(RS_SERVICE_TYPE_GXS_TRANS) {}
~RsGxsTransSerializer() {} virtual ~RsGxsTransSerializer() {}
RsItem* create_item(uint16_t service_id, uint8_t item_sub_id) const RsItem* create_item(uint16_t service_id, uint8_t item_sub_id) const
{ {

View file

@ -1056,7 +1056,7 @@ bool p3GxsTunnelService::locked_sendDHPublicKey(const DH *dh,const RsGxsId& own_
} }
RsGxsTunnelDHPublicKeyItem *dhitem = new RsGxsTunnelDHPublicKeyItem ; RsGxsTunnelDHPublicKeyItem *dhitem = new RsGxsTunnelDHPublicKeyItem ;
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
dhitem->public_key = BN_dup(dh->pub_key) ; dhitem->public_key = BN_dup(dh->pub_key) ;
#else #else
const BIGNUM *pub_key=NULL ; const BIGNUM *pub_key=NULL ;
@ -1140,7 +1140,7 @@ bool p3GxsTunnelService::locked_initDHSessionKey(DH *& dh)
return false ; return false ;
} }
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
BN_hex2bn(&dh->p,dh_prime_2048_hex.c_str()) ; BN_hex2bn(&dh->p,dh_prime_2048_hex.c_str()) ;
BN_hex2bn(&dh->g,"5") ; BN_hex2bn(&dh->g,"5") ;
#else #else

View file

@ -140,7 +140,6 @@ PUBLIC_HEADERS = retroshare/rsdisc.h \
retroshare/rsversion.h \ retroshare/rsversion.h \
retroshare/rsservicecontrol.h \ retroshare/rsservicecontrol.h \
HEADERS += plugins/pluginmanager.h \ HEADERS += plugins/pluginmanager.h \
plugins/dlfcn_win32.h \ plugins/dlfcn_win32.h \
rsitems/rspluginitems.h \ rsitems/rspluginitems.h \
@ -429,6 +428,7 @@ HEADERS += pqi/authssl.h \
pqi/pqissl.h \ pqi/pqissl.h \
pqi/pqissllistener.h \ pqi/pqissllistener.h \
pqi/pqisslpersongrp.h \ pqi/pqisslpersongrp.h \
pqi/pqissli2pbob.h \
pqi/pqissludp.h \ pqi/pqissludp.h \
pqi/pqisslproxy.h \ pqi/pqisslproxy.h \
pqi/pqistore.h \ pqi/pqistore.h \
@ -493,7 +493,9 @@ HEADERS += rsitems/rsitem.h \
rsitems/rsgxsupdateitems.h \ rsitems/rsgxsupdateitems.h \
rsitems/rsserviceinfoitems.h \ rsitems/rsserviceinfoitems.h \
HEADERS += services/p3msgservice.h \ HEADERS += services/autoproxy/p3i2pbob.h \
services/autoproxy/rsautoproxymonitor.h \
services/p3msgservice.h \
services/p3service.h \ services/p3service.h \
services/p3statusservice.h \ services/p3statusservice.h \
services/p3banlist.h \ services/p3banlist.h \
@ -518,6 +520,9 @@ HEADERS += util/folderiterator.h \
util/rsnet.h \ util/rsnet.h \
util/extaddrfinder.h \ util/extaddrfinder.h \
util/dnsresolver.h \ util/dnsresolver.h \
util/radix32.h \
util/radix64.h \
util/rsinitedptr.h \
util/rsprint.h \ util/rsprint.h \
util/rsstring.h \ util/rsstring.h \
util/rsstd.h \ util/rsstd.h \
@ -525,7 +530,6 @@ HEADERS += util/folderiterator.h \
util/rsversioninfo.h \ util/rsversioninfo.h \
util/rswin.h \ util/rswin.h \
util/rsrandom.h \ util/rsrandom.h \
util/radix64.h \
util/pugiconfig.h \ util/pugiconfig.h \
util/rsmemcache.h \ util/rsmemcache.h \
util/rstickevent.h \ util/rstickevent.h \
@ -580,6 +584,7 @@ SOURCES += pqi/authgpg.cc \
pqi/pqissl.cc \ pqi/pqissl.cc \
pqi/pqissllistener.cc \ pqi/pqissllistener.cc \
pqi/pqisslpersongrp.cc \ pqi/pqisslpersongrp.cc \
pqi/pqissli2pbob.cpp \
pqi/pqissludp.cc \ pqi/pqissludp.cc \
pqi/pqisslproxy.cc \ pqi/pqisslproxy.cc \
pqi/pqistore.cc \ pqi/pqistore.cc \
@ -638,7 +643,9 @@ SOURCES += serialiser/rsbaseserial.cc \
rsitems/rsgxsupdateitems.cc \ rsitems/rsgxsupdateitems.cc \
rsitems/rsserviceinfoitems.cc \ rsitems/rsserviceinfoitems.cc \
SOURCES += services/p3msgservice.cc \ SOURCES += services/autoproxy/rsautoproxymonitor.cc \
services/autoproxy/p3i2pbob.cc \
services/p3msgservice.cc \
services/p3service.cc \ services/p3service.cc \
services/p3statusservice.cc \ services/p3statusservice.cc \
services/p3banlist.cc \ services/p3banlist.cc \

View file

@ -245,7 +245,7 @@ sslcert::sslcert(X509 *x509, const RsPeerId& pid)
{ {
certificate = x509; certificate = x509;
id = pid; id = pid;
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
name = getX509CNString(x509->cert_info->subject); name = getX509CNString(x509->cert_info->subject);
org = getX509OrgString(x509->cert_info->subject); org = getX509OrgString(x509->cert_info->subject);
location = getX509LocString(x509->cert_info->subject); location = getX509LocString(x509->cert_info->subject);
@ -377,7 +377,7 @@ static int initLib = 0;
if (dh) if (dh)
{ {
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
BN_hex2bn(&dh->p,dh_prime_4096_hex.c_str()) ; BN_hex2bn(&dh->p,dh_prime_4096_hex.c_str()) ;
BN_hex2bn(&dh->g,"5") ; BN_hex2bn(&dh->g,"5") ;
#else #else
@ -599,7 +599,7 @@ bool AuthSSLimpl::SignData(const void *data, const uint32_t len, std::string &si
EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
unsigned int signlen = EVP_PKEY_size(mOwnPrivateKey); unsigned int signlen = EVP_PKEY_size(mOwnPrivateKey);
unsigned char signature[signlen]; unsigned char signature[signlen] = { 0 };
if (0 == EVP_SignInit(mdctx, EVP_sha1())) if (0 == EVP_SignInit(mdctx, EVP_sha1()))
{ {
@ -795,7 +795,7 @@ X509 *AuthSSLimpl::SignX509ReqWithGPG(X509_REQ *req, long /*days*/)
// The code has been copied in order to use the PGP signing instead of supplying the // The code has been copied in order to use the PGP signing instead of supplying the
// private EVP_KEY to ASN1_sign(), which would be another alternative. // private EVP_KEY to ASN1_sign(), which would be another alternative.
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
int (*i2d)(X509_CINF*, unsigned char**) = i2d_X509_CINF; int (*i2d)(X509_CINF*, unsigned char**) = i2d_X509_CINF;
X509_ALGOR *algor1 = x509->cert_info->signature; X509_ALGOR *algor1 = x509->cert_info->signature;
X509_ALGOR *algor2 = x509->sig_alg; X509_ALGOR *algor2 = x509->sig_alg;
@ -824,7 +824,7 @@ X509 *AuthSSLimpl::SignX509ReqWithGPG(X509_REQ *req, long /*days*/)
/* FIX ALGORITHMS */ /* FIX ALGORITHMS */
a = const_cast<X509_ALGOR*>(algor1); a = const_cast<X509_ALGOR*>(algor1);
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
ASN1_TYPE_free(a->parameter); ASN1_TYPE_free(a->parameter);
a->parameter=ASN1_TYPE_new(); a->parameter=ASN1_TYPE_new();
a->parameter->type=V_ASN1_NULL; a->parameter->type=V_ASN1_NULL;
@ -836,7 +836,7 @@ X509 *AuthSSLimpl::SignX509ReqWithGPG(X509_REQ *req, long /*days*/)
#endif #endif
a = const_cast<X509_ALGOR*>(algor2); a = const_cast<X509_ALGOR*>(algor2);
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
ASN1_TYPE_free(a->parameter); ASN1_TYPE_free(a->parameter);
a->parameter=ASN1_TYPE_new(); a->parameter=ASN1_TYPE_new();
a->parameter->type=V_ASN1_NULL; a->parameter->type=V_ASN1_NULL;
@ -851,7 +851,7 @@ X509 *AuthSSLimpl::SignX509ReqWithGPG(X509_REQ *req, long /*days*/)
std::cerr << "Algorithms Fixed" << std::endl; std::cerr << "Algorithms Fixed" << std::endl;
/* input buffer */ /* input buffer */
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
inl=i2d(data,NULL); inl=i2d(data,NULL);
buf_in=(unsigned char *)OPENSSL_malloc((unsigned int)inl); buf_in=(unsigned char *)OPENSSL_malloc((unsigned int)inl);
unsigned char *p=NULL; unsigned char *p=NULL;
@ -874,7 +874,7 @@ X509 *AuthSSLimpl::SignX509ReqWithGPG(X509_REQ *req, long /*days*/)
} }
std::cerr << "Buffers Allocated" << std::endl; std::cerr << "Buffers Allocated" << std::endl;
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
p=buf_in; p=buf_in;
i2d(data,&p); i2d(data,&p);
#endif #endif
@ -960,7 +960,7 @@ bool AuthSSLimpl::AuthX509WithGPG(X509 *x509,uint32_t& diagnostic)
} }
/* extract CN for peer Id */ /* extract CN for peer Id */
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
RsPgpId issuer(std::string(getX509CNString(x509->cert_info->issuer))); RsPgpId issuer(std::string(getX509CNString(x509->cert_info->issuer)));
#else #else
RsPgpId issuer(std::string(getX509CNString(X509_get_issuer_name(x509)))); RsPgpId issuer(std::string(getX509CNString(X509_get_issuer_name(x509))));
@ -979,7 +979,7 @@ bool AuthSSLimpl::AuthX509WithGPG(X509 *x509,uint32_t& diagnostic)
/*** NOW The Manual signing bit (HACKED FROM asn1/a_sign.c) ***/ /*** NOW The Manual signing bit (HACKED FROM asn1/a_sign.c) ***/
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
int (*i2d)(X509_CINF*, unsigned char**) = i2d_X509_CINF; int (*i2d)(X509_CINF*, unsigned char**) = i2d_X509_CINF;
ASN1_BIT_STRING *signature = x509->signature; ASN1_BIT_STRING *signature = x509->signature;
X509_CINF *data = x509->cert_info; X509_CINF *data = x509->cert_info;
@ -1000,7 +1000,7 @@ bool AuthSSLimpl::AuthX509WithGPG(X509 *x509,uint32_t& diagnostic)
int sigoutl=0; int sigoutl=0;
/* input buffer */ /* input buffer */
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
inl=i2d(data,NULL); inl=i2d(data,NULL);
buf_in=(unsigned char *)OPENSSL_malloc((unsigned int)inl); buf_in=(unsigned char *)OPENSSL_malloc((unsigned int)inl);
unsigned char *p=NULL; unsigned char *p=NULL;
@ -1033,7 +1033,7 @@ bool AuthSSLimpl::AuthX509WithGPG(X509 *x509,uint32_t& diagnostic)
std::cerr << "Buffers Allocated" << std::endl; std::cerr << "Buffers Allocated" << std::endl;
#endif #endif
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
p=buf_in; p=buf_in;
i2d(data,&p); i2d(data,&p);
#endif #endif
@ -1157,7 +1157,7 @@ static int verify_x509_callback(int preverify_ok, X509_STORE_CTX *ctx)
if(x509 != NULL) if(x509 != NULL)
{ {
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
RsPgpId gpgid (std::string(getX509CNString(x509->cert_info->issuer))); RsPgpId gpgid (std::string(getX509CNString(x509->cert_info->issuer)));
#else #else
RsPgpId gpgid (std::string(getX509CNString(X509_get_issuer_name(x509)))); RsPgpId gpgid (std::string(getX509CNString(X509_get_issuer_name(x509))));
@ -1165,7 +1165,7 @@ static int verify_x509_callback(int preverify_ok, X509_STORE_CTX *ctx)
if(gpgid.isNull()) if(gpgid.isNull())
{ {
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
std::cerr << "verify_x509_callback(): wrong PGP id \"" << std::string(getX509CNString(x509->cert_info->issuer)) << "\"" << std::endl; std::cerr << "verify_x509_callback(): wrong PGP id \"" << std::string(getX509CNString(x509->cert_info->issuer)) << "\"" << std::endl;
#else #else
std::cerr << "verify_x509_callback(): wrong PGP id \"" << std::string(getX509CNString(X509_get_issuer_name(x509))) << "\"" << std::endl; std::cerr << "verify_x509_callback(): wrong PGP id \"" << std::string(getX509CNString(X509_get_issuer_name(x509))) << "\"" << std::endl;
@ -1173,7 +1173,7 @@ static int verify_x509_callback(int preverify_ok, X509_STORE_CTX *ctx)
return false ; return false ;
} }
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
std::string sslcn = getX509CNString(x509->cert_info->subject); std::string sslcn = getX509CNString(x509->cert_info->subject);
#else #else
std::string sslcn = getX509CNString(X509_get_subject_name(x509)); std::string sslcn = getX509CNString(X509_get_subject_name(x509));
@ -1262,7 +1262,7 @@ int AuthSSLimpl::VerifyX509Callback(int preverify_ok, X509_STORE_CTX *ctx)
std::cerr << "(WW) Certificate was rejected because authentication failed. Diagnostic = " << auth_diagnostic << std::endl; std::cerr << "(WW) Certificate was rejected because authentication failed. Diagnostic = " << auth_diagnostic << std::endl;
return false; return false;
} }
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
RsPgpId pgpid(std::string(getX509CNString(X509_STORE_CTX_get_current_cert(ctx)->cert_info->issuer))); RsPgpId pgpid(std::string(getX509CNString(X509_STORE_CTX_get_current_cert(ctx)->cert_info->issuer)));
#else #else
RsPgpId pgpid(std::string(getX509CNString(X509_get_issuer_name(X509_STORE_CTX_get_current_cert(ctx))))); RsPgpId pgpid(std::string(getX509CNString(X509_get_issuer_name(X509_STORE_CTX_get_current_cert(ctx)))));
@ -1339,7 +1339,7 @@ bool AuthSSLimpl::encrypt(void *&out, int &outlen, const void *in, int inlen,
#endif #endif
return false; return false;
} else { } else {
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
public_key = mCerts[peerId]->certificate->cert_info->key->pkey; public_key = mCerts[peerId]->certificate->cert_info->key->pkey;
#else #else
public_key = X509_get0_pubkey(mCerts[peerId]->certificate) ; public_key = X509_get0_pubkey(mCerts[peerId]->certificate) ;
@ -1586,20 +1586,26 @@ bool AuthSSLimpl::FailedCertificate(X509 *x509, const RsPgpId& gpgid,
switch(auth_diagnostic) switch(auth_diagnostic)
{ {
case RS_SSL_HANDSHAKE_DIAGNOSTIC_CERTIFICATE_MISSING: RsServer::notify()->AddFeedItem(RS_FEED_ITEM_SEC_MISSING_CERTIFICATE, gpgid.toStdString(), sslid.toStdString(), sslcn, ip_address); case RS_SSL_HANDSHAKE_DIAGNOSTIC_CERTIFICATE_MISSING:
break ; RsServer::notify()->notifyConnectionWithoutCert();
case RS_SSL_HANDSHAKE_DIAGNOSTIC_CERTIFICATE_NOT_VALID: RsServer::notify()->AddFeedItem(RS_FEED_ITEM_SEC_BAD_CERTIFICATE, gpgid.toStdString(), sslid.toStdString(), sslcn, ip_address); RsServer::notify()->AddFeedItem(RS_FEED_ITEM_SEC_MISSING_CERTIFICATE, gpgid.toStdString(), sslid.toStdString(), sslcn, ip_address);
break ; break ;
case RS_SSL_HANDSHAKE_DIAGNOSTIC_ISSUER_UNKNOWN: RsServer::notify()->AddFeedItem(RS_FEED_ITEM_SEC_UNKNOWN_IN , gpgid.toStdString(), sslid.toStdString(), sslcn, ip_address); case RS_SSL_HANDSHAKE_DIAGNOSTIC_CERTIFICATE_NOT_VALID:
break ; RsServer::notify()->AddFeedItem(RS_FEED_ITEM_SEC_BAD_CERTIFICATE, gpgid.toStdString(), sslid.toStdString(), sslcn, ip_address);
case RS_SSL_HANDSHAKE_DIAGNOSTIC_MALLOC_ERROR: RsServer::notify()->AddFeedItem(RS_FEED_ITEM_SEC_INTERNAL_ERROR , gpgid.toStdString(), sslid.toStdString(), sslcn, ip_address); break ;
break ; case RS_SSL_HANDSHAKE_DIAGNOSTIC_ISSUER_UNKNOWN:
case RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE: RsServer::notify()->AddFeedItem(RS_FEED_ITEM_SEC_WRONG_SIGNATURE, gpgid.toStdString(), sslid.toStdString(), sslcn, ip_address); RsServer::notify()->AddFeedItem(RS_FEED_ITEM_SEC_UNKNOWN_IN , gpgid.toStdString(), sslid.toStdString(), sslcn, ip_address);
break ; break ;
case RS_SSL_HANDSHAKE_DIAGNOSTIC_OK: case RS_SSL_HANDSHAKE_DIAGNOSTIC_MALLOC_ERROR:
case RS_SSL_HANDSHAKE_DIAGNOSTIC_UNKNOWN: RsServer::notify()->AddFeedItem(RS_FEED_ITEM_SEC_INTERNAL_ERROR , gpgid.toStdString(), sslid.toStdString(), sslcn, ip_address);
default: break ;
RsServer::notify()->AddFeedItem(RS_FEED_ITEM_SEC_CONNECT_ATTEMPT, gpgid.toStdString(), sslid.toStdString(), sslcn, ip_address); case RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE:
RsServer::notify()->AddFeedItem(RS_FEED_ITEM_SEC_WRONG_SIGNATURE, gpgid.toStdString(), sslid.toStdString(), sslcn, ip_address);
break ;
case RS_SSL_HANDSHAKE_DIAGNOSTIC_OK:
case RS_SSL_HANDSHAKE_DIAGNOSTIC_UNKNOWN:
default:
RsServer::notify()->AddFeedItem(RS_FEED_ITEM_SEC_CONNECT_ATTEMPT, gpgid.toStdString(), sslid.toStdString(), sslcn, ip_address);
} }
#ifdef AUTHSSL_DEBUG #ifdef AUTHSSL_DEBUG

View file

@ -237,6 +237,7 @@ void p3Notify::notifyOwnStatusMessageChanged()
void p3Notify::notifyDiskFull (uint32_t location , uint32_t size_limit_in_MB ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyDiskFull (location,size_limit_in_MB) ; } void p3Notify::notifyDiskFull (uint32_t location , uint32_t size_limit_in_MB ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyDiskFull (location,size_limit_in_MB) ; }
void p3Notify::notifyPeerStatusChanged (const std::string& peer_id , uint32_t status ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyPeerStatusChanged (peer_id,status) ; } void p3Notify::notifyPeerStatusChanged (const std::string& peer_id , uint32_t status ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyPeerStatusChanged (peer_id,status) ; }
void p3Notify::notifyGxsChange (const RsGxsChanges& changes) {FOR_ALL_NOTIFY_CLIENTS (*it)->notifyGxsChange(changes) ;} void p3Notify::notifyGxsChange (const RsGxsChanges& changes) {FOR_ALL_NOTIFY_CLIENTS (*it)->notifyGxsChange(changes) ;}
void p3Notify::notifyConnectionWithoutCert () { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyConnectionWithoutCert(); }
void p3Notify::notifyPeerStatusChangedSummary () { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyPeerStatusChangedSummary() ; } void p3Notify::notifyPeerStatusChangedSummary () { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyPeerStatusChangedSummary() ; }
void p3Notify::notifyDiscInfoChanged () { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyDiscInfoChanged () ; } void p3Notify::notifyDiscInfoChanged () { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyDiscInfoChanged () ; }

View file

@ -112,6 +112,7 @@ class p3Notify: public RsNotify
void notifyDiskFull (uint32_t /* location */, uint32_t /* size limit in MB */) ; void notifyDiskFull (uint32_t /* location */, uint32_t /* size limit in MB */) ;
void notifyPeerStatusChanged (const std::string& /* peer_id */, uint32_t /* status */) ; void notifyPeerStatusChanged (const std::string& /* peer_id */, uint32_t /* status */) ;
void notifyGxsChange (const RsGxsChanges& /* changes */); void notifyGxsChange (const RsGxsChanges& /* changes */);
void notifyConnectionWithoutCert ();
void notifyPeerStatusChangedSummary () ; void notifyPeerStatusChangedSummary () ;
void notifyDiscInfoChanged () ; void notifyDiscInfoChanged () ;

View file

@ -521,12 +521,14 @@ int pqiperson::connect(uint32_t type, const sockaddr_storage &raddr,
return 0; return 0;
} }
pqiconnect *pqi = it->second;
#ifdef PERSON_DEBUG #ifdef PERSON_DEBUG
std::cerr << "pqiperson::connect() resetting for new connection attempt" << std::endl; std::cerr << "pqiperson::connect() resetting for new connection attempt" << std::endl;
#endif #endif
/* set the parameters */ /* set the parameters */
(it->second)->reset(); pqi->reset();
#ifdef PERSON_DEBUG #ifdef PERSON_DEBUG
std::cerr << "pqiperson::connect() clearing rate cap" << std::endl; std::cerr << "pqiperson::connect() clearing rate cap" << std::endl;
@ -538,22 +540,22 @@ int pqiperson::connect(uint32_t type, const sockaddr_storage &raddr,
#endif #endif
// These two are universal. // These two are universal.
(it->second)->connect_parameter(NET_PARAM_CONNECT_DELAY, delay); pqi->connect_parameter(NET_PARAM_CONNECT_DELAY, delay);
(it->second)->connect_parameter(NET_PARAM_CONNECT_TIMEOUT, timeout); pqi->connect_parameter(NET_PARAM_CONNECT_TIMEOUT, timeout);
// these 5 are only used by UDP connections. // these 5 are only used by UDP connections.
(it->second)->connect_parameter(NET_PARAM_CONNECT_PERIOD, period); pqi->connect_parameter(NET_PARAM_CONNECT_PERIOD, period);
(it->second)->connect_parameter(NET_PARAM_CONNECT_FLAGS, flags); pqi->connect_parameter(NET_PARAM_CONNECT_FLAGS, flags);
(it->second)->connect_parameter(NET_PARAM_CONNECT_BANDWIDTH, bandwidth); pqi->connect_parameter(NET_PARAM_CONNECT_BANDWIDTH, bandwidth);
(it->second)->connect_additional_address(NET_PARAM_CONNECT_PROXY, proxyaddr); pqi->connect_additional_address(NET_PARAM_CONNECT_PROXY, proxyaddr);
(it->second)->connect_additional_address(NET_PARAM_CONNECT_SOURCE, srcaddr); pqi->connect_additional_address(NET_PARAM_CONNECT_SOURCE, srcaddr);
// These are used by Proxy/Hidden // These are used by Proxy/Hidden
(it->second)->connect_parameter(NET_PARAM_CONNECT_DOMAIN_ADDRESS, domain_addr); pqi->connect_parameter(NET_PARAM_CONNECT_DOMAIN_ADDRESS, domain_addr);
(it->second)->connect_parameter(NET_PARAM_CONNECT_REMOTE_PORT, domain_port); pqi->connect_parameter(NET_PARAM_CONNECT_REMOTE_PORT, domain_port);
(it->second)->connect(raddr); pqi->connect(raddr);
// flag if we started a new connectionAttempt. // flag if we started a new connectionAttempt.
inConnectAttempt = true; inConnectAttempt = true;

View file

@ -361,7 +361,7 @@ void pqissl::getCryptoParams(RsPeerCryptoParams& params)
bool pqissl::actAsServer() bool pqissl::actAsServer()
{ {
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
return (bool)ssl_connection->server; return (bool)ssl_connection->server;
#else #else
return (bool)SSL_is_server(ssl_connection); return (bool)SSL_is_server(ssl_connection);
@ -1230,7 +1230,7 @@ int pqissl::Extract_Failed_SSL_Certificate()
RsPeerId sslid ; RsPeerId sslid ;
getX509id(peercert, sslid) ; getX509id(peercert, sslid) ;
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
RsPgpId gpgid(getX509CNString(peercert->cert_info->issuer)); RsPgpId gpgid(getX509CNString(peercert->cert_info->issuer));
std::string sslcn = getX509CNString(peercert->cert_info->subject); std::string sslcn = getX509CNString(peercert->cert_info->subject);
#else #else

View file

@ -0,0 +1,31 @@
#include "pqissli2pbob.h"
bool pqissli2pbob::connect_parameter(uint32_t type, const std::string &value)
{
if (type == NET_PARAM_CONNECT_DOMAIN_ADDRESS)
{
RS_STACK_MUTEX(mSslMtx);
// a new line must be appended!
mI2pAddr = value + '\n';
return true;
}
return pqissl::connect_parameter(type, value);
}
int pqissli2pbob::Basic_Connection_Complete()
{
int ret;
if ((ret = pqissl::Basic_Connection_Complete()) != 1)
{
// basic connection not complete.
return ret;
}
// send addr. (new line is already appended)
ret = send(sockfd, mI2pAddr.c_str(), mI2pAddr.length(), 0);
if (ret != (int)mI2pAddr.length())
return -1;
return 1;
}

View file

@ -0,0 +1,31 @@
#ifndef PQISSLI2PBOB_H
#define PQISSLI2PBOB_H
#include "pqi/pqissl.h"
/*
* This class is a minimal varied version of pqissl to work with I2P BOB tunnels.
* The only difference is that the [.b32].i2p addresses must be sent first.
*
* Everything else is untouched.
*/
class pqissli2pbob : public pqissl
{
public:
pqissli2pbob(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm)
: pqissl(l, parent, lm) {}
// NetInterface interface
public:
bool connect_parameter(uint32_t type, const std::string &value);
// pqissl interface
protected:
int Basic_Connection_Complete();
private:
std::string mI2pAddr;
};
#endif // PQISSLI2PBOB_H

View file

@ -493,7 +493,7 @@ int pqissllistenbase::continueSSL(IncomingSSLInfo& incoming_connexion_info, bool
#endif #endif
if(x509 != NULL) if(x509 != NULL)
{ {
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
incoming_connexion_info.gpgid = RsPgpId(std::string(getX509CNString(x509->cert_info->issuer))); incoming_connexion_info.gpgid = RsPgpId(std::string(getX509CNString(x509->cert_info->issuer)));
incoming_connexion_info.sslcn = getX509CNString(x509->cert_info->subject); incoming_connexion_info.sslcn = getX509CNString(x509->cert_info->subject);
#else #else
@ -892,7 +892,7 @@ int pqissllistener::completeConnection(int fd, IncomingSSLInfo& info)
AuthSSL::getAuthSSL()->CheckCertificate(newPeerId, peercert); AuthSSL::getAuthSSL()->CheckCertificate(newPeerId, peercert);
/* now need to get GPG id too */ /* now need to get GPG id too */
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
RsPgpId pgpid(std::string(getX509CNString(peercert->cert_info->issuer))); RsPgpId pgpid(std::string(getX509CNString(peercert->cert_info->issuer)));
#else #else
RsPgpId pgpid(std::string(getX509CNString(X509_get_issuer_name(peercert)))); RsPgpId pgpid(std::string(getX509CNString(X509_get_issuer_name(peercert))));

View file

@ -24,6 +24,7 @@
*/ */
#include "serialiser/rsserializer.h" #include "serialiser/rsserializer.h"
#include "services/autoproxy/rsautoproxymonitor.h"
#include "util/rsdebug.h" #include "util/rsdebug.h"
#include "pqi/pqisslpersongrp.h" #include "pqi/pqisslpersongrp.h"
@ -49,6 +50,7 @@ static struct RsLog::logInfo pqipersongrpzoneInfo = {RsLog::Default, "pqipersong
#endif #endif
#include "pqi/pqisslproxy.h" #include "pqi/pqisslproxy.h"
#include "pqi/pqissli2pbob.h"
pqilistener * pqisslpersongrp::locked_createListener(const struct sockaddr_storage &laddr) pqilistener * pqisslpersongrp::locked_createListener(const struct sockaddr_storage &laddr)
{ {
@ -76,29 +78,34 @@ pqiperson * pqisslpersongrp::locked_createPerson(const RsPeerId& id, pqilistener
std::cerr << std::endl; std::cerr << std::endl;
#endif #endif
pqisslproxy *pqis = new pqisslproxy((pqissllistener *) listener, pqip, mLinkMgr); // Use pqicI2PBOB for I2P
pqiconnect *pqicSOCKSProxy, *pqicI2PBOB;
/* construct the serialiser .... {
* Needs: pqisslproxy *pqis = new pqisslproxy((pqissllistener *) listener, pqip, mLinkMgr);
* * FileItem RsSerialiser *rss = new RsSerialiser();
* * FileData rss->addSerialType(new RsRawSerialiser());
* * ServiceGeneric pqicSOCKSProxy = new pqiconnect(pqip, rss, pqis);
*/ }
if (rsAutoProxyMonitor::instance()->isEnabled(autoProxyType::I2PBOB))
{
pqissli2pbob *pqis = new pqissli2pbob((pqissllistener *) listener, pqip, mLinkMgr);
RsSerialiser *rss = new RsSerialiser();
rss->addSerialType(new RsRawSerialiser());
pqicI2PBOB = new pqiconnect(pqip, rss, pqis);
} else {
pqicI2PBOB = pqicSOCKSProxy;
}
RsSerialiser *rss = new RsSerialiser();
rss->addSerialType(new RsRawSerialiser());
pqiconnect *pqisc = new pqiconnect(pqip, rss, pqis);
/* first select type based on peer */ /* first select type based on peer */
uint32_t typePeer = mPeerMgr->getHiddenType(id); uint32_t typePeer = mPeerMgr->getHiddenType(id);
switch (typePeer) { switch (typePeer) {
case RS_HIDDEN_TYPE_TOR: case RS_HIDDEN_TYPE_TOR:
pqip -> addChildInterface(PQI_CONNECT_HIDDEN_TOR_TCP, pqisc); pqip -> addChildInterface(PQI_CONNECT_HIDDEN_TOR_TCP, pqicSOCKSProxy);
break; break;
case RS_HIDDEN_TYPE_I2P: case RS_HIDDEN_TYPE_I2P:
pqip -> addChildInterface(PQI_CONNECT_HIDDEN_I2P_TCP, pqisc); pqip -> addChildInterface(PQI_CONNECT_HIDDEN_I2P_TCP, pqicI2PBOB);
break; break;
default: default:
/* peer is not a hidden one but we are */ /* peer is not a hidden one but we are */
@ -106,7 +113,7 @@ pqiperson * pqisslpersongrp::locked_createPerson(const RsPeerId& id, pqilistener
uint32_t typeOwn = mPeerMgr->getHiddenType(AuthSSL::getAuthSSL()->OwnId()); uint32_t typeOwn = mPeerMgr->getHiddenType(AuthSSL::getAuthSSL()->OwnId());
switch (typeOwn) { switch (typeOwn) {
case RS_HIDDEN_TYPE_I2P: case RS_HIDDEN_TYPE_I2P:
pqip -> addChildInterface(PQI_CONNECT_HIDDEN_I2P_TCP, pqisc); pqip -> addChildInterface(PQI_CONNECT_HIDDEN_I2P_TCP, pqicI2PBOB);
break; break;
default: default:
/* this case shouldn't happen! */ /* this case shouldn't happen! */
@ -117,7 +124,7 @@ pqiperson * pqisslpersongrp::locked_createPerson(const RsPeerId& id, pqilistener
std::cerr << " - hidden types: peer=" << typePeer << " own=" << typeOwn << std::endl; std::cerr << " - hidden types: peer=" << typePeer << " own=" << typeOwn << std::endl;
std::cerr << " --> falling back to Tor" << std::endl; std::cerr << " --> falling back to Tor" << std::endl;
case RS_HIDDEN_TYPE_TOR: case RS_HIDDEN_TYPE_TOR:
pqip -> addChildInterface(PQI_CONNECT_HIDDEN_TOR_TCP, pqisc); pqip -> addChildInterface(PQI_CONNECT_HIDDEN_TOR_TCP, pqicSOCKSProxy);
break; break;
} }
} }

View file

@ -81,7 +81,7 @@ private:
uint32_t mProxyState; uint32_t mProxyState;
std::string mDomainAddress; std::string mDomainAddress;
uint16_t mRemotePort; uint16_t mRemotePort;
}; };
#endif // MRK_PQI_SSL_PROXY_HEADER #endif // MRK_PQI_SSL_PROXY_HEADER

View file

@ -602,7 +602,7 @@ bool getX509id(X509 *x509, RsPeerId& xid)
} }
// get the signature from the cert, and copy to the array. // get the signature from the cert, and copy to the array.
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
ASN1_BIT_STRING *signature = x509->signature; ASN1_BIT_STRING *signature = x509->signature;
#else #else
const ASN1_BIT_STRING *signature = NULL ; const ASN1_BIT_STRING *signature = NULL ;
@ -700,7 +700,7 @@ int LoadCheckX509(const char *cert_file, RsPgpId& issuerName, std::string &locat
if (valid) if (valid)
{ {
// extract the name. // extract the name.
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
issuerName = RsPgpId(std::string(getX509CNString(x509->cert_info->issuer))); issuerName = RsPgpId(std::string(getX509CNString(x509->cert_info->issuer)));
location = getX509LocString(x509->cert_info->subject); location = getX509LocString(x509->cert_info->subject);
#else #else

View file

@ -60,6 +60,8 @@ public:
public: public:
RsMsgMetaData mMeta; RsMsgMetaData mMeta;
std::set<RsGxsMessageId> mOlderVersions ;
std::string mMsg; // UTF8 encoded. std::string mMsg; // UTF8 encoded.
std::list<RsGxsFile> mFiles; std::list<RsGxsFile> mFiles;

View file

@ -0,0 +1,103 @@
#pragma once
#include "retroshare/rstokenservice.h"
#include "retroshare/rsgxsifacehelper.h"
#include "retroshare/rsgxscommon.h"
/// Subservices identifiers (like port for TCP)
enum class GxsTransSubServices : uint16_t
{
UNKNOWN = 0x00,
TEST_SERVICE = 0x01,
P3_MSG_SERVICE = 0x02,
P3_CHAT_SERVICE = 0x03
};
/// Values must fit into uint8_t
enum class GxsTransItemsSubtypes : uint8_t
{
GXS_TRANS_SUBTYPE_MAIL = 0x01,
GXS_TRANS_SUBTYPE_RECEIPT = 0x02,
GXS_TRANS_SUBTYPE_GROUP = 0x03,
OUTGOING_RECORD_ITEM = 0x04
};
enum class GxsTransSendStatus : uint8_t
{
UNKNOWN = 0x00,
PENDING_PROCESSING = 0x01,
PENDING_PREFERRED_GROUP = 0x02,
PENDING_RECEIPT_CREATE = 0x03,
PENDING_RECEIPT_SIGNATURE = 0x04,
PENDING_SERIALIZATION = 0x05,
PENDING_PAYLOAD_CREATE = 0x06,
PENDING_PAYLOAD_ENCRYPT = 0x07,
PENDING_PUBLISH = 0x08,
/** This will be useful so the user can know if the mail reached at least
* some friend node, in case of internet connection interruption */
//PENDING_TRANSFER,
PENDING_RECEIPT_RECEIVE = 0x09,
/// Records with status >= RECEIPT_RECEIVED get deleted
RECEIPT_RECEIVED = 0x0a,
FAILED_RECEIPT_SIGNATURE = 0xf0,
FAILED_ENCRYPTION = 0xf1
};
typedef uint64_t RsGxsTransId;
class RsGxsTransGroup
{
public:
RsGroupMetaData mMeta;
};
class RsGxsTransMsg
{
public:
RsGxsTransMsg() : size(0),data(NULL) {}
virtual ~RsGxsTransMsg() { free(data) ; }
public:
RsMsgMetaData mMeta;
uint32_t size ;
uint8_t *data ;
};
struct RsGxsTransOutgoingRecord
{
GxsTransSendStatus status;
RsGxsId recipient;
RsGxsTransId trans_id;
GxsTransSubServices client_service;
uint32_t data_size ;
Sha1CheckSum data_hash ;
uint32_t send_TS ;
RsGxsGroupId group_id ;
};
class RsGxsTrans: public RsGxsIfaceHelper
{
public:
class GxsTransStatistics
{
public:
GxsTransStatistics() {}
RsGxsGroupId prefered_group_id ;
std::vector<RsGxsTransOutgoingRecord> outgoing_records;
};
RsGxsTrans(RsGxsIface *gxs) : RsGxsIfaceHelper(gxs) {}
virtual ~RsGxsTrans() {}
virtual bool getStatistics(GxsTransStatistics& stats)=0;
// virtual bool getGroupData(const uint32_t &token, std::vector<RsGxsTransGroup> &groups) = 0;
// virtual bool getPostData(const uint32_t &token, std::vector<RsGxsTransMsg> &posts) = 0;
};
extern RsGxsTrans *rsGxsTrans ;

View file

@ -78,7 +78,7 @@ class RsInit
/*! /*!
* Setup Hidden Location; * Setup Hidden Location;
*/ */
static bool SetHiddenLocation(const std::string& hiddenaddress, uint16_t port); static void SetHiddenLocation(const std::string& hiddenaddress, uint16_t port, bool useBob);
static bool LoadPassword(const std::string& passwd) ; static bool LoadPassword(const std::string& passwd) ;

View file

@ -228,6 +228,7 @@ class NotifyClient
virtual void notifyDiskFull (uint32_t /* location */, uint32_t /* size limit in MB */) {} virtual void notifyDiskFull (uint32_t /* location */, uint32_t /* size limit in MB */) {}
virtual void notifyPeerStatusChanged (const std::string& /* peer_id */, uint32_t /* status */) {} virtual void notifyPeerStatusChanged (const std::string& /* peer_id */, uint32_t /* status */) {}
virtual void notifyGxsChange (const RsGxsChanges& /* changes */) {} virtual void notifyGxsChange (const RsGxsChanges& /* changes */) {}
virtual void notifyConnectionWithoutCert () {}
/* one or more peers has changed the states */ /* one or more peers has changed the states */
virtual void notifyPeerStatusChangedSummary () {} virtual void notifyPeerStatusChangedSummary () {}

View file

@ -45,6 +45,8 @@ const int p3facemsgzone = 11453;
// TO SHUTDOWN THREADS. // TO SHUTDOWN THREADS.
#ifdef RS_ENABLE_GXS #ifdef RS_ENABLE_GXS
#include "services/autoproxy/rsautoproxymonitor.h"
#include "services/p3idservice.h" #include "services/p3idservice.h"
#include "services/p3gxscircles.h" #include "services/p3gxscircles.h"
#include "services/p3wiki.h" #include "services/p3wiki.h"
@ -89,6 +91,8 @@ void RsServer::rsGlobalShutDown()
mNetMgr->shutdown(); /* Handles UPnP */ mNetMgr->shutdown(); /* Handles UPnP */
rsAutoProxyMonitor::instance()->stopAllRSShutdown();
fullstop() ; fullstop() ;
// kill all registered service threads // kill all registered service threads

View file

@ -46,6 +46,7 @@
class p3heartbeat; class p3heartbeat;
class p3discovery2; class p3discovery2;
class p3I2pBob;
/* GXS Classes - just declare the classes. /* GXS Classes - just declare the classes.
so we don't have to totally recompile to switch */ so we don't have to totally recompile to switch */
@ -129,7 +130,7 @@ class RsServer: public RsControl, public RsTickingThread
* This function is responsible for ensuring Retroshare exits in a legal state: * This function is responsible for ensuring Retroshare exits in a legal state:
* i.e. releases all held resources and saves current configuration * i.e. releases all held resources and saves current configuration
*/ */
virtual void rsGlobalShutDown( ); virtual void rsGlobalShutDown( );
/****************************************/ /****************************************/
@ -164,6 +165,7 @@ class RsServer: public RsControl, public RsTickingThread
p3ChatService *chatSrv; p3ChatService *chatSrv;
p3StatusService *mStatusSrv; p3StatusService *mStatusSrv;
p3GxsTunnelService *mGxsTunnels; p3GxsTunnelService *mGxsTunnels;
p3I2pBob *mI2pBob;
// This list contains all threaded services. It will be used to shut them down properly. // This list contains all threaded services. It will be used to shut them down properly.

View file

@ -125,6 +125,8 @@ class RsInitConfig
std::string hiddenNodeAddress; std::string hiddenNodeAddress;
uint16_t hiddenNodePort; uint16_t hiddenNodePort;
bool hiddenNodeI2PBOB;
/* Logging */ /* Logging */
bool haveLogFile; bool haveLogFile;
bool outStderr; bool outStderr;
@ -794,13 +796,13 @@ void RsInit::setAutoLogin(bool autoLogin){
} }
/* Setup Hidden Location; */ /* Setup Hidden Location; */
bool RsInit::SetHiddenLocation(const std::string& hiddenaddress, uint16_t port) void RsInit::SetHiddenLocation(const std::string& hiddenaddress, uint16_t port, bool useBob)
{ {
/* parse the bugger (todo) */ /* parse the bugger (todo) */
rsInitConfig->hiddenNodeSet = true; rsInitConfig->hiddenNodeSet = true;
rsInitConfig->hiddenNodeAddress = hiddenaddress; rsInitConfig->hiddenNodeAddress = hiddenaddress;
rsInitConfig->hiddenNodePort = port; rsInitConfig->hiddenNodePort = port;
return true; rsInitConfig->hiddenNodeI2PBOB = useBob;
} }
@ -854,7 +856,10 @@ RsGRouter *rsGRouter = NULL ;
#include "upnp/upnphandler_miniupnp.h" #include "upnp/upnphandler_miniupnp.h"
#endif #endif
#endif #endif
#include "services/autoproxy/p3i2pbob.h"
#include "services/autoproxy/rsautoproxymonitor.h"
#include "services/p3gxsreputation.h" #include "services/p3gxsreputation.h"
#include "services/p3serviceinfo.h" #include "services/p3serviceinfo.h"
#include "services/p3heartbeat.h" #include "services/p3heartbeat.h"
@ -1046,8 +1051,11 @@ int RsServer::StartupRetroShare()
mPeerMgr->setManagers(mLinkMgr, mNetMgr); mPeerMgr->setManagers(mLinkMgr, mNetMgr);
mNetMgr->setManagers(mPeerMgr, mLinkMgr); mNetMgr->setManagers(mPeerMgr, mLinkMgr);
rsAutoProxyMonitor *autoProxy = rsAutoProxyMonitor::instance();
mI2pBob = new p3I2pBob(mPeerMgr);
autoProxy->addProxy(autoProxyType::I2PBOB, mI2pBob);
//load all the SSL certs as friends //load all the SSL certs as friends
// std::list<std::string> sslIds; // std::list<std::string> sslIds;
// AuthSSL::getAuthSSL()->getAuthenticatedList(sslIds); // AuthSSL::getAuthSSL()->getAuthenticatedList(sslIds);
@ -1261,12 +1269,6 @@ int RsServer::StartupRetroShare()
rsFiles = ftserver; rsFiles = ftserver;
/* create Cache Services */
std::string config_dir = rsAccounts->PathAccountDirectory();
std::string localcachedir = config_dir + "/cache/local";
std::string remotecachedir = config_dir + "/cache/remote";
std::vector<std::string> plugins_directories ; std::vector<std::string> plugins_directories ;
#ifdef __APPLE__ #ifdef __APPLE__
@ -1694,6 +1696,7 @@ int RsServer::StartupRetroShare()
//mConfigMgr->addConfiguration("photo.cfg", photo_ns); //mConfigMgr->addConfiguration("photo.cfg", photo_ns);
//mConfigMgr->addConfiguration("wire.cfg", wire_ns); //mConfigMgr->addConfiguration("wire.cfg", wire_ns);
#endif #endif
mConfigMgr->addConfiguration("I2PBOB.cfg", mI2pBob);
mPluginsManager->addConfigurations(mConfigMgr) ; mPluginsManager->addConfigurations(mConfigMgr) ;
@ -1739,12 +1742,46 @@ int RsServer::StartupRetroShare()
{ {
mPeerMgr->setOwnNetworkMode(RS_NET_MODE_EXT); mPeerMgr->setOwnNetworkMode(RS_NET_MODE_EXT);
mPeerMgr->setOwnVisState(RS_VS_DISC_FULL, RS_VS_DHT_FULL); mPeerMgr->setOwnVisState(RS_VS_DISC_FULL, RS_VS_DHT_FULL);
} }
if (rsInitConfig->hiddenNodeSet) if (rsInitConfig->hiddenNodeSet)
{ {
mPeerMgr->setupHiddenNode(rsInitConfig->hiddenNodeAddress, rsInitConfig->hiddenNodePort); std::cout << "RsServer::StartupRetroShare setting up hidden locations" << std::endl;
if (rsInitConfig->hiddenNodeI2PBOB) {
std::cout << "RsServer::StartupRetroShare setting up BOB" << std::endl;
// we need a local port!
mNetMgr->checkNetAddress();
// add i2p proxy
// bob will use this address
sockaddr_storage i2pInstance;
sockaddr_storage_ipv4_aton(i2pInstance, rsInitConfig->hiddenNodeAddress.c_str());
mPeerMgr->setProxyServerAddress(RS_HIDDEN_TYPE_I2P, i2pInstance);
std::string addr; // will be set by auto proxy service
uint16_t port = rsInitConfig->hiddenNodePort; // unused by bob
bool r = autoProxy->initialSetup(autoProxyType::I2PBOB, addr, port);
if (r && !addr.empty()) {
mPeerMgr->setupHiddenNode(addr, port);
// now enable bob
bobSettings bs;
autoProxy->taskSync(autoProxyType::I2PBOB, autoProxyTask::getSettings, &bs);
bs.enableBob = true;
autoProxy->taskSync(autoProxyType::I2PBOB, autoProxyTask::setSettings, &bs);
} else {
std::cerr << "RsServer::StartupRetroShare failed to receive keys" << std::endl;
/// TODO add notify for failed bob setup
}
} else {
mPeerMgr->setupHiddenNode(rsInitConfig->hiddenNodeAddress, rsInitConfig->hiddenNodePort);
}
std::cout << "RsServer::StartupRetroShare hidden location set up" << std::endl;
} }
else if (isHiddenNode) else if (isHiddenNode)
{ {
@ -1753,15 +1790,27 @@ int RsServer::StartupRetroShare()
mNetMgr -> checkNetAddress(); mNetMgr -> checkNetAddress();
if (rsInitConfig->hiddenNodeSet) {
// newly created location
// mNetMgr->checkNetAddress() will setup ports for us
// trigger updates for auto proxy services
std::vector<autoProxyType::autoProxyType_enum> types;
// i2p bob need to rebuild its command map
types.push_back(autoProxyType::I2PBOB);
rsAutoProxyMonitor::taskSync(types, autoProxyTask::reloadConfig);
}
/**************************************************************************/ /**************************************************************************/
/* startup (stuff dependent on Ids/peers is after this point) */ /* startup (stuff dependent on Ids/peers is after this point) */
/**************************************************************************/ /**************************************************************************/
autoProxy->startAll();
pqih->init_listener(); pqih->init_listener();
mNetMgr->addNetListener(pqih); /* add listener so we can reset all sockets later */ mNetMgr->addNetListener(pqih); /* add listener so we can reset all sockets later */
/**************************************************************************/ /**************************************************************************/
/* load caches and secondary data */ /* load caches and secondary data */
/**************************************************************************/ /**************************************************************************/
@ -1788,8 +1837,10 @@ int RsServer::StartupRetroShare()
/* Start up Threads */ /* Start up Threads */
/**************************************************************************/ /**************************************************************************/
#ifdef RS_ENABLE_GXS // auto proxy threads
startServiceThread(mI2pBob, "I2P-BOB");
#ifdef RS_ENABLE_GXS
// Must Set the GXS pointers before starting threads. // Must Set the GXS pointers before starting threads.
rsIdentity = mGxsIdService; rsIdentity = mGxsIdService;
rsGxsCircles = mGxsCircles; rsGxsCircles = mGxsCircles;
@ -1799,6 +1850,8 @@ int RsServer::StartupRetroShare()
rsPosted = mPosted; rsPosted = mPosted;
rsGxsForums = mGxsForums; rsGxsForums = mGxsForums;
rsGxsChannels = mGxsChannels; rsGxsChannels = mGxsChannels;
rsGxsTrans = mGxsTrans;
//rsPhoto = mPhoto; //rsPhoto = mPhoto;
//rsWire = mWire; //rsWire = mWire;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,250 @@
#ifndef P3I2PBOB_H
#define P3I2PBOB_H
#include <map>
#include <queue>
#include <sys/types.h>
#include <time.h>
#ifndef WINDOWS_SYS
#include <sys/socket.h>
#endif
#include "services/autoproxy/rsautoproxymonitor.h"
#include "util/rsthreads.h"
#include "pqi/p3cfgmgr.h"
/*
* This class implements I2P BOB (BASIC OPEN BRIDGE) communication to allow RS
* to automatically remote control I2P to setup the needed tunnel.
* BOB is a simple text-based interface: https://geti2p.net/en/docs/api/bob
*
* Note 1:
* One tunnel is enough even for hidden locations since it can be used
* bidirectional. (In contrast to what RS I2P users had to set up manually.)
*
* Note 2:
* BOB tunnels are no SOCKS tunnel. Therefore pqissli2pbob implements a simplified
* proxy specially for BOB tunnels.
*
* Note 3:
* BOB needs a unique name as an ID for each tunnel.
* We use 'RetroShare-' + 8 base32 characters.
*
* Design:
* The service uses three state machines to manage its task:
* int stateMachineBOB();
* mBOBState
* int stateMachineController();
* mState
* mTask
*
* stateMachineBOB:
* This state machine manages the low level communication with BOB. It basically has a linked
* list (currently a implemented as a std::map) that contains a command and the next
* state.
* Each high level operation (start up / shut down / get keys) is represented by a
* chain of states. E.g. the chain to retrieve new keys:
* mCommands[bobState::setnickN] = {setnick, bobState::newkeysN};
* mCommands[bobState::newkeysN] = {newkeys, bobState::getkeys};
* mCommands[bobState::getkeys] = {getkeys, bobState::clear};
* mCommands[bobState::clear] = {clear, bobState::quit};
* mCommands[bobState::quit] = {quit, bobState::cleared};
*
* stateMachineController:
* This state machone manages the high level tasks.
* It is controlled by mState and mTask.
*
* mTast:
* Tracks the high level operation (like start up).
* It will keep its value even when a task is done to track
* the requested BOB state.
* When other operations are performed like a conection check
* the last task gets backed up and is later restored again
*
* mState:
* This state lives only for one operation an manages the communication
* with the BOB instance. This is basically connecting, starting BOB
* protocol and disconnecting
*
* How a task looks like:
* 1) RS sets task using the ticket system
* 2) stateMachineController connects to BOBs control port, sets mBobState to a lists head
* 3) stateMachineBOB processes command chain
* 4) stateMachineBOB is done and sets mBobState to cleared signaling that the connection
* is cleared and can be closed
* 5) stateMachineController disconnects from BOBs control port and updates mState
*/
///
/// \brief The controllerState enum
/// States for the controller to keep track of what he is currently doing
enum controllerState {
csIdel,
csDoConnect,
csConnected,
csWaitForBob,
csDoDisconnect,
csDisconnected,
csError
};
///
/// \brief The controllerTask enum
/// This state tracks the controllers tast (e.g. setup a BOB tunnel or shut down
/// an existing one).
enum controllerTask {
ctIdle,
ctRunSetUp,
ctRunShutDown,
ctRunGetKeys,
ctRunCheck
};
///
/// \brief The bobState enum
/// One state for each message
///
enum bobState {
bsCleared,
bsSetnickC, // chain head for only client tunnel
bsSetnickN, // chain head for getting new (server) keys
bsSetnickS, // chain head for client and server tunnel
bsGetnick,
bsNewkeysC, // part of chain for only client tunnel
bsNewkeysN, // part of chain for getting new (server) keys
bsGetkeys,
bsSetkeys,
bsInhost,
bsOuthost,
bsInport,
bsOutport,
bsInlength,
bsOutlength,
bsInvariance,
bsOutvariance,
bsInquantity,
bsOutquantity,
bsQuiet,
bsStart,
bsStop,
bsClear,
bsList, // chain head for 'list' command
bsQuit
};
///
/// \brief The bobStateInfo struct
/// State machine with commands
/// \todo This could be replaced by a linked list instead of a map
struct bobStateInfo {
std::string command;
bobState nextState;
};
struct bobSettings {
bool enableBob; ///< This field is used by the pqi subsystem to determinine whether SOCKS proxy or BOB is used for I2P connections
std::string keys; ///< (optional) server keys
std::string addr; ///< (optional) hidden service addr. in base32 form
int8_t inLength;
int8_t inQuantity;
int8_t inVariance;
int8_t outLength;
int8_t outQuantity;
int8_t outVariance;
};
///
/// \brief The bobStates struct
/// This container struct is used to pass all states.
/// Additionally, the tunnel name is included to to show it in the GUI.
/// The advantage of a struct is that it can be forward declared.
struct bobStates {
bobState bs;
controllerState cs;
controllerTask ct;
std::string tunnelName;
};
class p3PeerMgr;
class p3I2pBob : public RsTickingThread, public p3Config, public autoProxyService
{
public:
p3I2pBob(p3PeerMgr *peerMgr);
// autoProxyService interface
public:
bool isEnabled();
bool initialSetup(std::string &addr, uint16_t &);
void processTaskAsync(taskTicket *ticket);
void processTaskSync(taskTicket *ticket);
static std::string keyToBase32Addr(const std::string &key);
// RsTickingThread interface
public:
void data_tick();
private:
int stateMachineBOB();
int stateMachineBOB_locked_failure(const std::string &answer, const bobStateInfo &currentState);
int stateMachineController();
int stateMachineController_locked_idle();
int stateMachineController_locked_connected();
int stateMachineController_locked_disconnected();
int stateMachineController_locked_error();
// p3Config interface
protected:
RsSerialiser *setupSerialiser();
bool saveList(bool &cleanup, std::list<RsItem *> &lst);
bool loadList(std::list<RsItem *> &load);
private:
// helpers
void getBOBSettings(bobSettings *settings);
void setBOBSettings(const bobSettings *settings);
void getStates(bobStates *bs);
std::string executeCommand(const std::string &command);
bool connectI2P();
bool disconnectI2P();
void finalizeSettings_locked();
void updateSettings_locked();
std::string recv();
// states for state machines
controllerState mState;
controllerTask mTask;
// used to store old state when in error state
// mStateOld is also used as a flag when an error occured in BOB protocol
controllerState mStateOld;
// mTaskOld is used to keep the previous task (start up / shut down) when requesting keys or checking the connection
controllerTask mTaskOld;
bobSettings mSetting;
bobState mBOBState;
// used variables
p3PeerMgr *mPeerMgr;
bool mConfigLoaded;
int mSocket;
time_t mLastProxyCheck;
sockaddr_storage mI2PProxyAddr;
std::map<bobState, bobStateInfo> mCommands;
std::string mErrorMsg;
std::string mTunnelName;
std::queue<taskTicket *> mPending;
taskTicket *mProcessing;
// mutex
RsMutex mLock;
};
#endif // P3I2PBOB_H

View file

@ -0,0 +1,303 @@
#include "rsautoproxymonitor.h"
#include <unistd.h> /* for usleep() */
rsAutoProxyMonitor *rsAutoProxyMonitor::mInstance = NULL;
rsAutoProxyMonitor::rsAutoProxyMonitor()
: mRSShutDown(false), mLock("rs auto proxy monitor")
{
mProxies.clear();
}
rsAutoProxyMonitor *rsAutoProxyMonitor::instance()
{
if (mInstance == NULL)
mInstance = new rsAutoProxyMonitor();
return mInstance;
}
void rsAutoProxyMonitor::addProxy(autoProxyType::autoProxyType_enum type, autoProxyService *service)
{
RS_STACK_MUTEX(mLock);
if (mProxies.find(type) != mProxies.end())
std::cerr << "sAutoProxyMonitor::addProxy type " << type << " already added - OVERWRITING" << std::endl;
mProxies[type] = service;
}
void rsAutoProxyMonitor::startAll()
{
// create ticket
taskTicket *tt = getTicket();
tt->cb = this;
tt->task = autoProxyTask::start;
{
std::map<autoProxyType::autoProxyType_enum, autoProxyService*>::const_iterator it;
// fill types
RS_STACK_MUTEX(mLock);
for (it = mProxies.begin(); it != mProxies.end(); ++it)
if (it->second->isEnabled())
tt->types.push_back(it->first);
}
task(tt);
}
void rsAutoProxyMonitor::stopAll()
{
// create ticket
taskTicket *tt = getTicket();
tt->cb = this;
tt->task = autoProxyTask::stop;
{
std::map<autoProxyType::autoProxyType_enum, autoProxyService*>::const_iterator it;
// fill types
RS_STACK_MUTEX(mLock);
for (it = mProxies.begin(); it != mProxies.end(); ++it)
if (it->second->isEnabled())
tt->types.push_back(it->first);
}
task(tt);
}
void rsAutoProxyMonitor::stopAllRSShutdown()
{
{
RS_STACK_MUTEX(mLock);
mRSShutDown = true;
// remove disabled services
std::vector<autoProxyType::autoProxyType_enum> toRemove;
std::map<autoProxyType::autoProxyType_enum, autoProxyService*>::const_iterator it;
for (it = mProxies.begin(); it != mProxies.end(); ++it) {
if (!it->second->isEnabled()) {
toRemove.push_back(it->first);
}
}
std::vector<autoProxyType::autoProxyType_enum>::const_iterator it2;
for (it2 = toRemove.begin(); it2 != toRemove.end(); ++it2) {
mProxies.erase(*it2);
}
}
// stop all remaining
stopAll();
// wait for shutdown of all services
uint32_t t = 0, timeout = 15;
do {
usleep(1000 * 1000);
RS_STACK_MUTEX(mLock);
std::cout << "(II) waiting for auto proxy service(s) to shut down " << t << "/" << timeout << " (remaining: " << mProxies.size() << ")" << std::endl;
if (mProxies.empty())
break;
t++;
} while (t < timeout );
}
bool rsAutoProxyMonitor::isEnabled(autoProxyType::autoProxyType_enum t)
{
autoProxyService *s = lookUpService(t);
if (s == NULL)
return false;
return s->isEnabled();
}
bool rsAutoProxyMonitor::initialSetup(autoProxyType::autoProxyType_enum t, std::string &addr, uint16_t &port)
{
autoProxyService *s = lookUpService(t);
if (s == NULL)
return false;
return s->initialSetup(addr, port);
}
void rsAutoProxyMonitor::task(taskTicket *ticket)
{
// sanity checks
if (!ticket->async && ticket->types.size() > 1) {
std::cerr << "(WW) rsAutoProxyMonitor::task synchronous call to multiple services. This can cause problems!" << std::endl;
}
if (ticket->async && !ticket->cb && ticket->data) {
std::cerr << "(WW) rsAutoProxyMonitor::task asynchronous call with data but no callback. This will likely causes memory leak!" << std::endl;
}
if (ticket->types.size() > 1 && ticket->data) {
std::cerr << "(WW) rsAutoProxyMonitor::task call with data to multiple services. This will likely causes memory leak!" << std::endl;
}
std::vector<autoProxyType::autoProxyType_enum>::const_iterator it;
for (it = ticket->types.begin(); it != ticket->types.end(); ++it) {
autoProxyService* s = lookUpService(*it);
if (s == NULL)
continue;
if (ticket->async) {
// copy ticket
taskTicket *tt = new taskTicket();
*tt = *ticket;
tt->types.clear();
tt->types.push_back(*it);
s->processTaskAsync(tt);
} else {
s->processTaskSync(ticket);
}
}
}
void rsAutoProxyMonitor::taskAsync(autoProxyType::autoProxyType_enum type, autoProxyTask::autoProxyTask_enum task, autoProxyCallback *cb, void *data)
{
std::vector<autoProxyType::autoProxyType_enum> types;
types.push_back(type);
taskAsync(types, task, cb, data);
}
void rsAutoProxyMonitor::taskAsync(std::vector<autoProxyType::autoProxyType_enum> types, autoProxyTask::autoProxyTask_enum task, autoProxyCallback *cb, void *data)
{
if (!isAsyncTask(task)) {
// Usually the services will reject this ticket.
// Just print a warning - maybe there is some special case where this is a good idea.
std::cerr << "(WW) rsAutoProxyMonitor::taskAsync called with a synchronous task!" << std::endl;
}
taskTicket *tt = getTicket();
tt->task = task;
tt->types = types;
if (cb)
tt->cb = cb;
if (data)
tt->data = data;
instance()->task(tt);
// tickets were copied, clean up
delete tt;
}
void rsAutoProxyMonitor::taskSync(autoProxyType::autoProxyType_enum type, autoProxyTask::autoProxyTask_enum task, void *data)
{
std::vector<autoProxyType::autoProxyType_enum> types;
types.push_back(type);
taskSync(types, task, data);
}
void rsAutoProxyMonitor::taskSync(std::vector<autoProxyType::autoProxyType_enum> types, autoProxyTask::autoProxyTask_enum task, void *data)
{
if (isAsyncTask(task)) {
// Usually the services will reject this ticket.
// Just print a warning - maybe there is some special case where this is a good idea.
std::cerr << "(WW) rsAutoProxyMonitor::taskSync called with an asynchronous task!" << std::endl;
}
taskTicket *tt = getTicket();
tt->async = false;
tt->task = task;
tt->types = types;
if (data)
tt->data = data;
instance()->task(tt);
// call done, clean up
delete tt;
}
void rsAutoProxyMonitor::taskError(taskTicket *t)
{
taskDone(t, autoProxyStatus::error);
}
void rsAutoProxyMonitor::taskDone(taskTicket *t, autoProxyStatus::autoProxyStatus_enum status)
{
bool cleanUp = false;
t->result = status;
if (t->cb) {
t->cb->taskFinished(t);
if (t != NULL) {
// callack did not clean up properly
std::cerr << "(WW) rsAutoProxyMonitor::taskFinish callback did not clean up!" << std::endl;
cleanUp = true;
}
} else if (t->async){
// async and no callback
// we must take care of deleting
cleanUp = true;
if(t->data)
std::cerr << "(WW) rsAutoProxyMonitor::taskFinish async call with data attached but no callback set!" << std::endl;
}
if (cleanUp) {
if (t->data) {
std::cerr << "(WW) rsAutoProxyMonitor::taskFinish will try to delete void pointer!" << std::endl;
#pragma GCC diagnostic ignored "-Wdelete-incomplete"
delete t->data;
#pragma GCC diagnostic pop
t->data = NULL;
}
delete t;
t = NULL;
}
}
taskTicket *rsAutoProxyMonitor::getTicket()
{
taskTicket *tt = new taskTicket();
tt->cb = NULL;
tt->data = NULL;
tt->async = true;
tt->result = autoProxyStatus::undefined;
return tt;
}
void rsAutoProxyMonitor::taskFinished(taskTicket *&ticket)
{
{
RS_STACK_MUTEX(mLock);
if (mRSShutDown && ticket->task == autoProxyTask::stop) {
mProxies.erase(ticket->types.front());
}
}
// clean up
if (ticket->data) {
std::cerr << "rsAutoProxyMonitor::taskFinished data set. Will try to delete void pointer" << std::endl;
#pragma GCC diagnostic ignored "-Wdelete-incomplete"
delete ticket->data;
#pragma GCC diagnostic pop
ticket->data = NULL;
}
delete ticket;
ticket = NULL;
}
autoProxyService *rsAutoProxyMonitor::lookUpService(autoProxyType::autoProxyType_enum t)
{
RS_STACK_MUTEX(mLock);
std::map<autoProxyType::autoProxyType_enum, autoProxyService*>::const_iterator itService;
if ((itService = mProxies.find(t)) != mProxies.end()) {
return itService->second;
}
std::cerr << "sAutoProxyMonitor::lookUpService no service for type " << t << " found!" << std::endl;
return NULL;
}
bool rsAutoProxyMonitor::isAsyncTask(autoProxyTask::autoProxyTask_enum t)
{
switch (t) {
case autoProxyTask::start:
case autoProxyTask::stop:
case autoProxyTask::receiveKey:
return true;
break;
default:
break;
}
return false;
}

View file

@ -0,0 +1,216 @@
#ifndef RSAUTOPROXYMONITOR_H
#define RSAUTOPROXYMONITOR_H
#include <vector>
#include <map>
#include <util/rsthreads.h>
class autoProxyCallback;
namespace autoProxyType {
enum autoProxyType_enum {
I2PBOB
};
}
namespace autoProxyTask {
enum autoProxyTask_enum {
/* async tasks */
start, ///< start up proxy
stop, ///< shut down proxy
receiveKey, ///< renew proxy key (if any)
proxyStatusCheck, ///< use to check if the proxy is still running
/* sync tasks */
status, ///< get status from auto proxy
getSettings, ///< get setting from auto proxy
setSettings, ///< set setting of auto proxy
reloadConfig, ///< signal config reload/rebuild
getErrorInfo ///< get error information from auto proxy
};
}
namespace autoProxyStatus {
enum autoProxyStatus_enum {
undefined, ///< undefined - usually not yet set
disabled, ///< used when a task cannot be done (e.g. a disabled service cannot be startet or stopped)
offline, ///< proxy is not set up
online, ///< proxy is set up
ok, ///< generic ok
error ///< generic error
};
}
struct taskTicket {
///
/// \brief types auto proxy service types that should get the ticket
///
std::vector<autoProxyType::autoProxyType_enum> types;
///
/// \brief task the task to satisfy
///
autoProxyTask::autoProxyTask_enum task;
///
/// \brief cb (optional) callback that gets called once the task is done
///
autoProxyCallback *cb;
///
/// \brief result (optional) result
///
autoProxyStatus::autoProxyStatus_enum result;
///
/// \brief data (optional) service dependent data
///
/// Needs to be allocated and freed by caller!
///
void *data;
///
/// \brief async is the call Asynchronous
///
/// Will create a copy of the ticket for each
/// service and delete the original ticket.
///
bool async;
};
class autoProxyCallback {
public:
///
/// \brief taskFinished called when a task is finished
/// \param ticket
///
/// Remove everything: ticket and attached data if any!
///
virtual void taskFinished(taskTicket *&ticket) = 0;
};
class autoProxyService {
public:
///
/// \brief isEnabled must be provided to directly get a result without going through the ticket system
/// \return whether the auto proxy service is enabled or not
///
virtual bool isEnabled() = 0;
///
/// \brief initialSetup used when creating a node
/// \param addr new address for the hidden service
/// \param port new port for the hidden service
/// \return true on success
///
/// This function is used to do an initial setup when creating a new hidden node.
/// Nothing has been set up at this point to the auto proxy service must take care
/// of everything (e.g. starting (and stoping) of needed threads)
///
virtual bool initialSetup(std::string &addr, uint16_t &port) = 0;
///
/// \brief processTaskAsync adds a ticket to the auto proxies task list
/// \param ticket
///
/// Don't call the callback in this function as this can cause dead locks!
///
virtual void processTaskAsync(taskTicket *ticket) = 0;
///
/// \brief processTaskSync taskTicket must be satisfied immediately
/// \param ticket
///
virtual void processTaskSync(taskTicket *ticket) = 0;
};
class rsAutoProxyMonitor : autoProxyCallback
{
public:
static rsAutoProxyMonitor *instance();
///
/// \brief addProxy adds a new auto proxy service to the monitor
/// \param type type of the new auto proxy service
/// \param service pointer to the service
///
void addProxy(autoProxyType::autoProxyType_enum type, autoProxyService *service);
// global functions
void startAll();
void stopAll();
void stopAllRSShutdown();
bool isEnabled(autoProxyType::autoProxyType_enum t);
// use this when creating a new node
bool initialSetup(autoProxyType::autoProxyType_enum t, std::string &addr, uint16_t &port);
///
/// \brief task Sends a task to all requested services
/// \param ticket Ticket containing required information
///
/// There are two kind of tasks: asyn and sync.
/// All tasks that involve communication with the target program (e.g. I2P or Tor) are asynchronous.
/// All other task are synchronous (e.g. getting settings)
///
///
/// Synchronous:
/// When you want to get the settings from a service you can call task() with a ticket only listing
/// one service and data pointing to the service's settings class/struct. Set async to false so
/// that the service gets your original ticket. Ther service will process the request (get settings)
/// immediately and when the call to task() is done you can access the settings from your ticket.
///
/// When additionally a call back is set the service will also call it. This can cause deadlocks!
///
///
/// Asynchronous:
/// When you want to start up all services or request new keys for all services you can call task() with a list
/// of services and set async to true. When each service has fullfilled the resquest he will
/// use the callback. The original caller ticket will be copied and each call to the callback
/// will use its copy of the original ticket. The attached data is not copied so each service gets
/// the same pointer!
///
///
/// Note:
/// Services should not delet or allocate anything unless no call back is provided and it is an
/// async call. In that case the service should delete the ticket and the attacked data.
/// Otherwise the caller must take care of cleaning up.
/// This class provides two wrappers to take care of this that should be used: taskError and taskDone
///
/// Note2:
/// This function is private so that each user must use the wrappers taskAsync and taskSync that include
/// more sanity checks
///
private:
void task(taskTicket *ticket);
public:
static void taskAsync(autoProxyType::autoProxyType_enum type, autoProxyTask::autoProxyTask_enum task, autoProxyCallback *cb = NULL, void *data = NULL);
static void taskAsync(std::vector<autoProxyType::autoProxyType_enum> types, autoProxyTask::autoProxyTask_enum task, autoProxyCallback *cb = NULL, void *data = NULL);
static void taskSync (autoProxyType::autoProxyType_enum type, autoProxyTask::autoProxyTask_enum task, void *data = NULL);
static void taskSync (std::vector<autoProxyType::autoProxyType_enum> types, autoProxyTask::autoProxyTask_enum task, void *data = NULL);
// usefull helpers
static void taskError(taskTicket *t);
static void taskDone(taskTicket *t, autoProxyStatus::autoProxyStatus_enum status);
static taskTicket *getTicket();
// autoProxyCallback interface
public:
void taskFinished(taskTicket *&ticket);
private:
rsAutoProxyMonitor();
autoProxyService *lookUpService(autoProxyType::autoProxyType_enum t);
static bool isAsyncTask(autoProxyTask::autoProxyTask_enum t);
std::map<autoProxyType::autoProxyType_enum, autoProxyService*> mProxies;
bool mRSShutDown;
RsMutex mLock;
static rsAutoProxyMonitor *mInstance;
};
#endif // RSAUTOPROXYMONITOR_H

View file

@ -2259,7 +2259,7 @@ void p3MsgService::sendDistantMsgItem(RsMsgItem *msgitem)
msg_serialized_data, msg_serialized_rssize, msg_serialized_data, msg_serialized_rssize,
signing_key_id, grouter_message_id ); signing_key_id, grouter_message_id );
RsGxsTransId gxsMailId; RsGxsTransId gxsMailId;
mGxsTransServ.sendMail( gxsMailId, GxsTransSubServices::P3_MSG_SERVICE, mGxsTransServ.sendData( gxsMailId, GxsTransSubServices::P3_MSG_SERVICE,
signing_key_id, destination_key_id, signing_key_id, destination_key_id,
msg_serialized_data, msg_serialized_rssize ); msg_serialized_data, msg_serialized_rssize );

View file

@ -90,7 +90,7 @@ static int clear_tou_socket_error(int s);
#include "tou.h" #include "tou.h"
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
//static void BIO_set_shutdown(BIO *a,int s) { a->shutdown=s; } //static void BIO_set_shutdown(BIO *a,int s) { a->shutdown=s; }
static int BIO_get_shutdown(BIO *a) { return a->shutdown; } static int BIO_get_shutdown(BIO *a) { return a->shutdown; }

View file

@ -0,0 +1,50 @@
#ifndef RADIX32_H
#define RADIX32_H
#include <string>
#include <string.h>
#include <vector>
#include <stdint.h>
class Radix32
{
public:
static std::string encode(const std::vector<uint8_t> &in) {
return encode(in.data(), in.size());
}
static std::string encode(const uint8_t *data, size_t len) {
std::string out = "";
size_t pos = 1;
uint8_t bits = 8, index;
uint16_t tmp = data[0]; // need min. 16 bits here
while (bits > 0 || pos < len) {
if (bits < 5) {
if (pos < len) {
tmp <<= 8;
tmp |= data[pos++] & 0xFF;
bits += 8;
} else { // last byte
tmp <<= (5 - bits);
bits = 5;
}
}
bits -= 5;
index = (tmp >> bits) & 0x1F;
out.push_back(bintoasc()[index]);
}
// append padding
while(out.length() % 4 != 0)
out.push_back('=');
return out;
}
private:
static const inline char *bintoasc() { static const char bta[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; return bta ; }
};
#endif // RADIX32_H

View file

@ -57,6 +57,10 @@
#include <errno.h> #include <errno.h>
#endif #endif
#ifndef __GLIBC__
#define canonicalize_file_name(p) realpath(p, NULL)
#endif
/**** /****
* #define RSDIR_DEBUG 1 * #define RSDIR_DEBUG 1
****/ ****/

View file

@ -126,3 +126,24 @@ std::string RsUtil::HashId(const std::string &id, bool reverse)
// out << std::setprecision(15) << getCurrentTS(); // out << std::setprecision(15) << getCurrentTS();
// return out.str(); // return out.str();
//} //}
std::vector<uint8_t> RsUtil::BinToSha256(const std::vector<uint8_t> &in)
{
std::vector<uint8_t> out;
SHA256_CTX *sha_ctx = new SHA256_CTX;
uint8_t sha_hash[SHA256_DIGEST_LENGTH] = {0};
SHA256_Init(sha_ctx);
SHA256_Update(sha_ctx, in.data(), in.size());
SHA256_Final(sha_hash, sha_ctx);
for(uint16_t i = 0; i < SHA256_DIGEST_LENGTH; i++)
{
out.push_back(sha_hash[i]);
}
/* cleanup */
delete sha_ctx;
return out;
}

View file

@ -30,6 +30,7 @@
#include <inttypes.h> #include <inttypes.h>
#include <string> #include <string>
#include <vector>
namespace RsUtil { namespace RsUtil {
@ -38,6 +39,7 @@ 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, bool hex=false); std::string NumberToString(uint64_t n, bool hex=false);
std::string HashId(const std::string &id, bool reverse = false); std::string HashId(const std::string &id, bool reverse = false);
std::vector<uint8_t> BinToSha256(const std::vector<uint8_t> &in);
//std::string AccurateTimeString(); //std::string AccurateTimeString();

View file

@ -508,7 +508,7 @@ bool RsRecogn::itemToRadix64(RsItem *item, std::string &radstr)
std::string RsRecogn::getRsaKeyId(RSA *pubkey) std::string RsRecogn::getRsaKeyId(RSA *pubkey)
{ {
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
int len = BN_num_bytes(pubkey -> n); int len = BN_num_bytes(pubkey -> n);
unsigned char tmp[len]; unsigned char tmp[len];
BN_bn2bin(pubkey -> n, tmp); BN_bn2bin(pubkey -> n, tmp);

View file

@ -61,6 +61,16 @@ int RS_pthread_setname_np(pthread_t __target_thread, const char *__buf) {
#include <iostream> #include <iostream>
#endif #endif
void RsThread::go()
{
mShouldStopSemaphore.set(0) ;
mHasStoppedSemaphore.set(0) ;
runloop();
mHasStoppedSemaphore.set(1);
mShouldStopSemaphore.set(0);
}
void *RsThread::rsthread_init(void* p) void *RsThread::rsthread_init(void* p)
{ {
RsThread *thread = (RsThread *) p; RsThread *thread = (RsThread *) p;
@ -76,7 +86,7 @@ void *RsThread::rsthread_init(void* p)
std::cerr << "[Thread ID:" << std::hex << pthread_self() << std::dec << "] thread is started. Calling runloop()..." << std::endl; std::cerr << "[Thread ID:" << std::hex << pthread_self() << std::dec << "] thread is started. Calling runloop()..." << std::endl;
#endif #endif
thread -> runloop(); thread->go();
return NULL; return NULL;
} }
RsThread::RsThread() RsThread::RsThread()
@ -216,14 +226,11 @@ RsTickingThread::RsTickingThread()
void RsSingleJobThread::runloop() void RsSingleJobThread::runloop()
{ {
mHasStoppedSemaphore.set(0) ;
run() ; run() ;
} }
void RsTickingThread::runloop() void RsTickingThread::runloop()
{ {
mHasStoppedSemaphore.set(0) ; // first time we are 100% the thread is actually running.
#ifdef DEBUG_THREADS #ifdef DEBUG_THREADS
THREAD_DEBUG << "RsTickingThread::runloop(). Setting stopped=0" << std::endl; THREAD_DEBUG << "RsTickingThread::runloop(). Setting stopped=0" << std::endl;
#endif #endif
@ -235,7 +242,6 @@ void RsTickingThread::runloop()
#ifdef DEBUG_THREADS #ifdef DEBUG_THREADS
THREAD_DEBUG << "pqithreadstreamer::runloop(): asked to stop. setting hasStopped=1, and returning. Thread ends." << std::endl; THREAD_DEBUG << "pqithreadstreamer::runloop(): asked to stop. setting hasStopped=1, and returning. Thread ends." << std::endl;
#endif #endif
mHasStoppedSemaphore.set(1);
return ; return ;
} }

View file

@ -263,6 +263,7 @@ class RsThread
protected: protected:
virtual void runloop() =0; /* called once the thread is started. Should be overloaded by subclasses. */ virtual void runloop() =0; /* called once the thread is started. Should be overloaded by subclasses. */
void go() ; // this one calls runloop and also sets the flags correctly when the thread is finished running.
RsSemaphore mHasStoppedSemaphore; RsSemaphore mHasStoppedSemaphore;
RsSemaphore mShouldStopSemaphore; RsSemaphore mShouldStopSemaphore;

View file

@ -25,7 +25,7 @@
#include <stdio.h> #include <stdio.h>
#if !defined(WINDOWS_SYS) && !defined(__ANDROID__) #if defined(__linux__) && defined(__GLIBC__)
#include <stdlib.h> #include <stdlib.h>
#include <execinfo.h> #include <execinfo.h>
@ -110,13 +110,13 @@ static inline void print_stacktrace(FILE *out = stderr, unsigned int max_frames
free(symbollist); free(symbollist);
} }
#else // !defined(WINDOWS_SYS) && !defined(__ANDROID__) #else // defined(__linux__) && defined(__GLIBC__)
static inline void print_stacktrace(FILE *out = stderr, unsigned int max_frames = 63) static inline void print_stacktrace(FILE *out = stderr, unsigned int max_frames = 63)
{ {
(void) max_frames; (void) max_frames;
fprintf(out, "TODO: 2016/01/01 print_stacktrace not implemented yet for WINDOWS_SYS and ANDROID\n"); fprintf(out, "TODO: 2016/01/01 print_stacktrace not implemented yet for WINDOWS_SYS and ANDROID\n");
} }
#endif // !defined(WINDOWS_SYS) && !defined(__ANDROID__) #endif // defined(__linux__) && defined(__GLIBC__)
#endif // _STACKTRACE_H_ #endif // _STACKTRACE_H_

View file

@ -45,7 +45,7 @@ void test_secret_key(const ops_secret_key_t *skey)
{ {
RSA* test=RSA_new(); RSA* test=RSA_new();
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
test->n=BN_dup(skey->public_key.key.rsa.n); test->n=BN_dup(skey->public_key.key.rsa.n);
test->e=BN_dup(skey->public_key.key.rsa.e); test->e=BN_dup(skey->public_key.key.rsa.e);
test->d=BN_dup(skey->key.rsa.d); test->d=BN_dup(skey->key.rsa.d);
@ -402,7 +402,7 @@ ops_boolean_t ops_dsa_verify(const unsigned char *hash,size_t hash_length,
osig=DSA_SIG_new(); osig=DSA_SIG_new();
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
osig->r=sig->r; osig->r=sig->r;
osig->s=sig->s; osig->s=sig->s;
#else #else
@ -417,7 +417,7 @@ ops_boolean_t ops_dsa_verify(const unsigned char *hash,size_t hash_length,
already_said=ops_true ; already_said=ops_true ;
} }
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
osig->r=NULL; // in this case, the values are not copied. osig->r=NULL; // in this case, the values are not copied.
osig->s=NULL; osig->s=NULL;
#endif #endif
@ -427,7 +427,7 @@ ops_boolean_t ops_dsa_verify(const unsigned char *hash,size_t hash_length,
} }
odsa=DSA_new(); odsa=DSA_new();
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
odsa->p=dsa->p; odsa->p=dsa->p;
odsa->q=dsa->q; odsa->q=dsa->q;
odsa->g=dsa->g; odsa->g=dsa->g;
@ -471,7 +471,7 @@ ops_boolean_t ops_dsa_verify(const unsigned char *hash,size_t hash_length,
return ops_false ; return ops_false ;
} }
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
osig->r=NULL; osig->r=NULL;
osig->s=NULL; osig->s=NULL;
@ -503,7 +503,7 @@ int ops_rsa_public_decrypt(unsigned char *out,const unsigned char *in,
int n; int n;
orsa=RSA_new(); orsa=RSA_new();
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
orsa->n=rsa->n; orsa->n=rsa->n;
orsa->e=rsa->e; orsa->e=rsa->e;
#else #else
@ -512,7 +512,7 @@ int ops_rsa_public_decrypt(unsigned char *out,const unsigned char *in,
n=RSA_public_decrypt(length,in,out,orsa,RSA_NO_PADDING); n=RSA_public_decrypt(length,in,out,orsa,RSA_NO_PADDING);
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
orsa->n=orsa->e=NULL; orsa->n=orsa->e=NULL;
#endif #endif
RSA_free(orsa); RSA_free(orsa);
@ -538,7 +538,7 @@ int ops_rsa_private_encrypt(unsigned char *out,const unsigned char *in,
int n; int n;
orsa=RSA_new(); orsa=RSA_new();
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
orsa->n=rsa->n; // XXX: do we need n? orsa->n=rsa->n; // XXX: do we need n?
orsa->d=srsa->d; orsa->d=srsa->d;
orsa->p=srsa->q; orsa->p=srsa->q;
@ -564,7 +564,7 @@ int ops_rsa_private_encrypt(unsigned char *out,const unsigned char *in,
n=RSA_private_encrypt(length,in,out,orsa,RSA_NO_PADDING); n=RSA_private_encrypt(length,in,out,orsa,RSA_NO_PADDING);
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
orsa->n=orsa->d=orsa->p=orsa->q=NULL; orsa->n=orsa->d=orsa->p=orsa->q=NULL;
orsa->e=NULL; orsa->e=NULL;
#endif #endif
@ -592,7 +592,7 @@ int ops_rsa_private_decrypt(unsigned char *out,const unsigned char *in,
char errbuf[1024]; char errbuf[1024];
orsa=RSA_new(); orsa=RSA_new();
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
orsa->n=rsa->n; // XXX: do we need n? orsa->n=rsa->n; // XXX: do we need n?
orsa->d=srsa->d; orsa->d=srsa->d;
orsa->p=srsa->q; orsa->p=srsa->q;
@ -618,7 +618,7 @@ int ops_rsa_private_decrypt(unsigned char *out,const unsigned char *in,
ERR_error_string(err,&errbuf[0]); ERR_error_string(err,&errbuf[0]);
fprintf(stderr,"openssl error : %s\n",errbuf); fprintf(stderr,"openssl error : %s\n",errbuf);
} }
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
orsa->n=orsa->d=orsa->p=orsa->q=NULL; orsa->n=orsa->d=orsa->p=orsa->q=NULL;
orsa->e=NULL; orsa->e=NULL;
#endif #endif
@ -644,7 +644,7 @@ int ops_rsa_public_encrypt(unsigned char *out,const unsigned char *in,
// printf("ops_rsa_public_encrypt: length=%ld\n", length); // printf("ops_rsa_public_encrypt: length=%ld\n", length);
orsa=RSA_new(); orsa=RSA_new();
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
orsa->n=rsa->n; orsa->n=rsa->n;
orsa->e=rsa->e; orsa->e=rsa->e;
#else #else
@ -664,7 +664,7 @@ int ops_rsa_public_encrypt(unsigned char *out,const unsigned char *in,
BIO_free(fd_out) ; BIO_free(fd_out) ;
} }
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
orsa->n=orsa->e=NULL; orsa->n=orsa->e=NULL;
#endif #endif
RSA_free(orsa); RSA_free(orsa);
@ -744,7 +744,7 @@ ops_boolean_t ops_rsa_generate_keypair(const int numbits, const unsigned long e,
skey->public_key.days_valid=0; skey->public_key.days_valid=0;
skey->public_key.algorithm= OPS_PKA_RSA; skey->public_key.algorithm= OPS_PKA_RSA;
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
skey->public_key.key.rsa.n=BN_dup(rsa->n); skey->public_key.key.rsa.n=BN_dup(rsa->n);
skey->public_key.key.rsa.e=BN_dup(rsa->e); skey->public_key.key.rsa.e=BN_dup(rsa->e);
skey->key.rsa.d=BN_dup(rsa->d); skey->key.rsa.d=BN_dup(rsa->d);
@ -766,7 +766,7 @@ ops_boolean_t ops_rsa_generate_keypair(const int numbits, const unsigned long e,
skey->octet_count=0; skey->octet_count=0;
skey->checksum=0; skey->checksum=0;
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
skey->key.rsa.p=BN_dup(rsa->p); skey->key.rsa.p=BN_dup(rsa->p);
skey->key.rsa.q=BN_dup(rsa->q); skey->key.rsa.q=BN_dup(rsa->q);
skey->key.rsa.u=BN_mod_inverse(NULL,rsa->p, rsa->q, ctx); skey->key.rsa.u=BN_mod_inverse(NULL,rsa->p, rsa->q, ctx);
@ -888,7 +888,7 @@ DSA_SIG* ops_dsa_sign(unsigned char* hashbuf, unsigned hashsize, const ops_dsa_s
DSA_SIG *dsasig; DSA_SIG *dsasig;
odsa=DSA_new(); odsa=DSA_new();
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
odsa->p=dsa->p; odsa->p=dsa->p;
odsa->q=dsa->q; odsa->q=dsa->q;
odsa->g=dsa->g; odsa->g=dsa->g;
@ -901,7 +901,7 @@ DSA_SIG* ops_dsa_sign(unsigned char* hashbuf, unsigned hashsize, const ops_dsa_s
dsasig=DSA_do_sign(hashbuf,hashsize,odsa); dsasig=DSA_do_sign(hashbuf,hashsize,odsa);
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
odsa->p=odsa->q=odsa->g=odsa->pub_key=odsa->priv_key=NULL; odsa->p=odsa->q=odsa->g=odsa->pub_key=odsa->priv_key=NULL;
#endif #endif
DSA_free(odsa); DSA_free(odsa);

View file

@ -298,7 +298,7 @@ static ops_boolean_t dsa_sign(ops_hash_t *hash, const ops_dsa_public_key_t *dsa,
dsasig=ops_dsa_sign(hashbuf, hashsize, sdsa, dsa); dsasig=ops_dsa_sign(hashbuf, hashsize, sdsa, dsa);
// convert and write the sig out to memory // convert and write the sig out to memory
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
ops_write_mpi(dsasig->r, cinfo); ops_write_mpi(dsasig->r, cinfo);
ops_write_mpi(dsasig->s, cinfo); ops_write_mpi(dsasig->s, cinfo);
#else #else

View file

@ -149,6 +149,8 @@ GenCertDialog::GenCertDialog(bool onlyGenerateIdentity, QWidget *parent)
connect(ui.node_input, SIGNAL(textChanged(QString)), this, SLOT(updateCheckLabels())); connect(ui.node_input, SIGNAL(textChanged(QString)), this, SLOT(updateCheckLabels()));
connect(ui.reuse_existing_node_CB, SIGNAL(toggled(bool)), this, SLOT(updateCheckLabels())); connect(ui.reuse_existing_node_CB, SIGNAL(toggled(bool)), this, SLOT(updateCheckLabels()));
connect(ui.cbUseBob, SIGNAL(clicked(bool)), this, SLOT(useBobChecked(bool)));;
entropy_timer = new QTimer ; entropy_timer = new QTimer ;
entropy_timer->start(20) ; entropy_timer->start(20) ;
QObject::connect(entropy_timer,SIGNAL(timeout()),this,SLOT(grabMouse())) ; QObject::connect(entropy_timer,SIGNAL(timeout()),this,SLOT(grabMouse())) ;
@ -161,12 +163,12 @@ GenCertDialog::GenCertDialog(bool onlyGenerateIdentity, QWidget *parent)
ui.keylength_comboBox->addItem("Very high (4096 bits)", QVariant(4096)); ui.keylength_comboBox->addItem("Very high (4096 bits)", QVariant(4096));
#if QT_VERSION >= 0x040700 #if QT_VERSION >= 0x040700
ui.node_input->setPlaceholderText(tr("[Required] Examples: Home, Laptop,...(Visible to friends).")) ; ui.node_input->setPlaceholderText(tr("Node name")) ;
ui.hiddenaddr_input->setPlaceholderText(tr("[Optional] Tor/I2P address (Example: xa76giaf6ifda7ri63i263.onion)")) ; ui.hiddenaddr_input->setPlaceholderText(tr("Tor/I2P address")) ;
ui.name_input->setPlaceholderText(tr("[Required] Visible to friends, and friends of friends.")); ui.name_input->setPlaceholderText(tr("Username"));
ui.nickname_input->setPlaceholderText(tr("[Optional] Used to write in chat rooms and forums. Can be set later.")); ui.nickname_input->setPlaceholderText(tr("Identity name"));
ui.password_input->setPlaceholderText(tr("[Required] This password protects your data. Dont forget it!")); ui.password_input->setPlaceholderText(tr("Password"));
ui.password_input_2->setPlaceholderText(tr("[Required] Type the same password again here.")); ui.password_input_2->setPlaceholderText(tr("Password again"));
#endif #endif
ui.nickname_input->setMaxLength(RSID_MAXIMUM_NICKNAME_SIZE); ui.nickname_input->setMaxLength(RSID_MAXIMUM_NICKNAME_SIZE);
@ -240,7 +242,7 @@ void GenCertDialog::mouseMoveEvent(QMouseEvent *e)
void GenCertDialog::setupState() void GenCertDialog::setupState()
{ {
bool adv_state = ui.adv_checkbox->isChecked(); bool adv_state = ui.adv_checkbox->isChecked();
if(!adv_state) if(!adv_state)
{ {
@ -294,12 +296,13 @@ void GenCertDialog::setupState()
ui.entropy_bar->setVisible(true); ui.entropy_bar->setVisible(true);
ui.genButton->setVisible(true); ui.genButton->setVisible(true);
ui.genButton->setText(generate_new?tr("Generate new profile and node"):tr("Generate new node")); ui.genButton->setText(generate_new?tr("Generate"):tr("Generate"));
ui.hiddenaddr_input->setVisible(hidden_state); ui.hiddenaddr_input->setVisible(hidden_state);
ui.hiddenaddr_label->setVisible(hidden_state); ui.hiddenaddr_label->setVisible(hidden_state);
ui.hiddenport_label->setVisible(hidden_state); ui.hiddenport_label->setVisible(hidden_state);
ui.hiddenport_spinBox->setVisible(hidden_state); ui.hiddenport_spinBox->setVisible(hidden_state);
ui.cbUseBob->setVisible(hidden_state);
if(mEntropyOk && mAllFieldsOk) if(mEntropyOk && mAllFieldsOk)
{ {
@ -379,7 +382,22 @@ void GenCertDialog::updateCheckLabels()
else else
ui.randomness_check_LB->setPixmap(QPixmap(IMAGE_BAD)) ; ui.randomness_check_LB->setPixmap(QPixmap(IMAGE_BAD)) ;
setupState(); setupState();
}
void GenCertDialog::useBobChecked(bool checked)
{
if (checked) {
ui.hiddenaddr_input->setPlaceholderText(tr("I2P instance address with BOB enabled"));
ui.hiddenaddr_label->setText(tr("I2P instance address"));
ui.hiddenport_spinBox->setEnabled(false);
} else {
ui.hiddenaddr_input->setPlaceholderText(tr("hidden service address"));
ui.hiddenaddr_label->setText(tr("hidden address"));
ui.hiddenport_spinBox->setEnabled(true);
}
} }
bool GenCertDialog::importIdentity() bool GenCertDialog::importIdentity()
@ -454,15 +472,13 @@ void GenCertDialog::genPerson()
{ {
std::string hl = ui.hiddenaddr_input->text().toStdString(); std::string hl = ui.hiddenaddr_input->text().toStdString();
uint16_t port = ui.hiddenport_spinBox->value(); uint16_t port = ui.hiddenport_spinBox->value();
if (!RsInit::SetHiddenLocation(hl, port)) /* parses it */ bool useBob = ui.cbUseBob->isChecked();
{
/* Message Dialog */ if (useBob && hl.empty())
QMessageBox::warning(this, hl = "127.0.0.1";
tr("Invalid hidden node"),
tr("Please enter a valid address of the form: 31769173498.onion:7800 or [52 characters].b32.i2p"), RsInit::SetHiddenLocation(hl, port, useBob); /* parses it */
QMessageBox::Ok);
return;
}
isHiddenLoc = true; isHiddenLoc = true;
} }

View file

@ -45,6 +45,7 @@ private slots:
void switchReuseExistingNode(); void switchReuseExistingNode();
void grabMouse(); void grabMouse();
void updateCheckLabels(); void updateCheckLabels();
void useBobChecked(bool checked);
private: private:
void initKeyList(); void initKeyList();

View file

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>533</width> <width>520</width>
<height>544</height> <height>541</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -34,13 +34,16 @@
<number>0</number> <number>0</number>
</property> </property>
<item> <item>
<widget class="QFrame" name="frame"> <widget class="QFrame" name="profileframe">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::StyledPanel</enum> <enum>QFrame::StyledPanel</enum>
</property> </property>
@ -48,13 +51,16 @@
<enum>QFrame::Raised</enum> <enum>QFrame::Raised</enum>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>9</number>
</property>
<item> <item>
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
<property name="pixmap"> <property name="pixmap">
<pixmap resource="images.qrc">:/images/logo/logo_spash2.png</pixmap> <pixmap resource="images.qrc">:/images/logo/logo_web_nobackground.png</pixmap>
</property> </property>
<property name="scaledContents"> <property name="scaledContents">
<bool>false</bool> <bool>false</bool>
@ -105,19 +111,63 @@
</layout> </layout>
</item> </item>
<item> <item>
<widget class="QFrame" name="profile_frame"> <widget class="QGroupBox" name="profile_groupBox">
<property name="styleSheet"> <property name="styleSheet">
<string notr="true"/> <string notr="true"/>
</property> </property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>24</number>
</property>
<property name="topMargin">
<number>24</number>
</property>
<property name="rightMargin">
<number>24</number>
</property>
<property name="bottomMargin">
<number>24</number>
</property>
<item row="0" column="0"> <item row="0" column="0">
<layout class="QGridLayout" name="profilGLayout"> <layout class="QGridLayout" name="profilGLayout">
<item row="14" column="2">
<widget class="QComboBox" name="keylength_comboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>PGP Key Length</string>
</property>
<property name="accessibleDescription">
<string/>
</property>
</widget>
</item>
<item row="18" column="1">
<widget class="QLabel" name="randomness_label_">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/randomness.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="7" column="3"> <item row="7" column="3">
<widget class="QLabel" name="password_check_LB"> <widget class="QLabel" name="password_check_LB">
<property name="text"> <property name="text">
@ -125,17 +175,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="15" column="0"> <item row="8" column="2">
<widget class="QLabel" name="keylength_label">
<property name="text">
<string>PGP key length</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="9" column="2">
<widget class="QLineEdit" name="password_input_2"> <widget class="QLineEdit" name="password_input_2">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
@ -163,42 +203,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="0">
<widget class="QLabel" name="password_label">
<property name="toolTip">
<string>This password is for PGP</string>
</property>
<property name="text">
<string>Password</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="15" column="2">
<widget class="QComboBox" name="keylength_comboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="password_label_2">
<property name="toolTip">
<string>This password is for PGP</string>
</property>
<property name="text">
<string>Password (check)</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="18" column="2"> <item row="18" column="2">
<widget class="QProgressBar" name="entropy_bar"> <widget class="QProgressBar" name="entropy_bar">
<property name="sizePolicy"> <property name="sizePolicy">
@ -229,7 +233,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="16" column="2"> <item row="15" column="2">
<widget class="QComboBox" name="nodeType_CB"> <widget class="QComboBox" name="nodeType_CB">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -271,16 +275,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0">
<widget class="QLabel" name="node_label">
<property name="text">
<string>Node name</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="4" column="3"> <item row="4" column="3">
<widget class="QLabel" name="profile_name_check_LB"> <widget class="QLabel" name="profile_name_check_LB">
<property name="text"> <property name="text">
@ -365,7 +359,7 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="9" column="3"> <item row="8" column="3">
<widget class="QLabel" name="password2_check_LB"> <widget class="QLabel" name="password2_check_LB">
<property name="text"> <property name="text">
<string/> <string/>
@ -394,46 +388,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0">
<widget class="QLabel" name="name_label">
<property name="text">
<string>Profile name</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="18" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Randomness</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="16" column="0">
<widget class="QLabel" name="label_nodeType">
<property name="text">
<string>Node type</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="17" column="0">
<widget class="QLabel" name="hiddenaddr_label">
<property name="text">
<string>hidden address</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="17" column="2"> <item row="17" column="2">
<layout class="QHBoxLayout" name="hiddenInfoHLayout"> <layout class="QHBoxLayout" name="hiddenInfoHLayout">
<property name="spacing"> <property name="spacing">
@ -496,22 +450,16 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="cbUseBob">
<property name="text">
<string>Use BOB</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item row="10" column="0"> <item row="9" column="2">
<widget class="QLabel" name="nickname_label">
<property name="toolTip">
<string/>
</property>
<property name="text">
<string>Chat identity</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="10" column="2">
<widget class="QLineEdit" name="nickname_input"> <widget class="QLineEdit" name="nickname_input">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -564,6 +512,191 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="1">
<widget class="QLabel" name="name_label">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/person.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QLabel" name="nickname_label">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolTip">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/chat-lobbies.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="node_label">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/network.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QLabel" name="keylength_label">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/keyring.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLabel" name="password_label_2">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolTip">
<string>This password is for PGP</string>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/password.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLabel" name="password_label">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolTip">
<string>This password is for PGP</string>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/password.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="17" column="1">
<widget class="QLabel" name="hiddenaddr_label">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/hidden.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="15" column="1">
<widget class="QLabel" name="label_nodeType">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/netgraph.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
</layout> </layout>

View file

@ -1403,7 +1403,7 @@ void NewsFeed::openChat(const RsPeerId &peerId)
ChatDialog::chatFriend(ChatId(peerId)); ChatDialog::chatFriend(ChatId(peerId));
} }
void NewsFeed::openComments(uint32_t /*type*/, const RsGxsGroupId &/*groupId*/, const RsGxsMessageId &/*msgId*/, const QString &/*title*/) void NewsFeed::openComments(uint32_t /*type*/, const RsGxsGroupId &/*groupId*/, const QVector<RsGxsMessageId>& versions,const RsGxsMessageId &/*msgId*/, const QString &/*title*/)
{ {
std::cerr << "NewsFeed::openComments() Not Handled Yet"; std::cerr << "NewsFeed::openComments() Not Handled Yet";
std::cerr << std::endl; std::cerr << std::endl;

View file

@ -58,7 +58,7 @@ public:
virtual QScrollArea *getScrollArea(); virtual QScrollArea *getScrollArea();
virtual void deleteFeedItem(QWidget *item, uint32_t type); virtual void deleteFeedItem(QWidget *item, uint32_t type);
virtual void openChat(const RsPeerId& peerId); virtual void openChat(const RsPeerId& peerId);
virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, const QString &title); virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const QVector<RsGxsMessageId> &versions, const RsGxsMessageId &msgId, const QString &title);
static void testFeeds(uint notifyFlags); static void testFeeds(uint notifyFlags);
static void testFeed(FeedNotify *feedNotify); static void testFeed(FeedNotify *feedNotify);

View file

@ -411,7 +411,13 @@ void PostedItem::loadComments()
if (mFeedHolder) if (mFeedHolder)
{ {
QString title = QString::fromUtf8(mPost.mMeta.mMsgName.c_str()); QString title = QString::fromUtf8(mPost.mMeta.mMsgName.c_str());
mFeedHolder->openComments(0, mPost.mMeta.mGroupId, mPost.mMeta.mMsgId, title);
#warning (csoler) Posted item versions not handled yet. When it is the case, start here.
QVector<RsGxsMessageId> post_versions ;
post_versions.push_back(mPost.mMeta.mMsgId) ;
mFeedHolder->openComments(0, mPost.mMeta.mGroupId, post_versions,mPost.mMeta.mMsgId, title);
} }
} }

View file

@ -139,9 +139,9 @@ void PostedListWidget::openChat(const RsPeerId & /*peerId*/)
return; return;
} }
void PostedListWidget::openComments(uint32_t /*feed_type*/, const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, const QString &title) void PostedListWidget::openComments(uint32_t /*feed_type*/, const RsGxsGroupId &groupId, const QVector<RsGxsMessageId> &versions, const RsGxsMessageId &msgId, const QString &title)
{ {
emit loadComment(groupId, msgId, title); emit loadComment(groupId, versions,msgId, title);
} }
void PostedListWidget::newPost() void PostedListWidget::newPost()

View file

@ -52,7 +52,7 @@ public:
virtual QScrollArea *getScrollArea(); virtual QScrollArea *getScrollArea();
virtual void deleteFeedItem(QWidget *item, uint32_t type); virtual void deleteFeedItem(QWidget *item, uint32_t type);
virtual void openChat(const RsPeerId& peerId); virtual void openChat(const RsPeerId& peerId);
virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, const QString &title); virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const QVector<RsGxsMessageId> &versions, const RsGxsMessageId &msgId, const QString &title);
/* GXS functions */ /* GXS functions */
virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req); virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req);

View file

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>516</width> <width>440</width>
<height>569</height> <height>350</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -17,7 +17,10 @@
<iconset resource="images.qrc"> <iconset resource="images.qrc">
<normaloff>:/images/logo/logo_32.png</normaloff>:/images/logo/logo_32.png</iconset> <normaloff>:/images/logo/logo_32.png</normaloff>:/images/logo/logo_32.png</iconset>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_2"> <property name="autoFillBackground">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="StartDialogVLayout">
<property name="leftMargin"> <property name="leftMargin">
<number>0</number> <number>0</number>
</property> </property>
@ -31,296 +34,324 @@
<number>0</number> <number>0</number>
</property> </property>
<item> <item>
<layout class="QGridLayout" name="mainGLayout"> <widget class="QFrame" name="loginframe">
<property name="leftMargin"> <property name="autoFillBackground">
<number>0</number> <bool>false</bool>
</property> </property>
<property name="rightMargin"> <property name="styleSheet">
<number>0</number> <string notr="true"/>
</property> </property>
<property name="bottomMargin"> <property name="frameShape">
<number>0</number> <enum>QFrame::StyledPanel</enum>
</property> </property>
<item row="0" column="0" colspan="4"> <layout class="QGridLayout" name="loginframeGLayout">
<layout class="QGridLayout" name="topGLayout"> <property name="leftMargin">
<item row="0" column="0"> <number>0</number>
<spacer name="horizontalSpacer"> </property>
<property name="orientation"> <property name="topMargin">
<enum>Qt::Horizontal</enum> <number>0</number>
</property> </property>
<property name="sizeHint" stdset="0"> <property name="rightMargin">
<size> <number>0</number>
<width>40</width> </property>
<height>20</height> <property name="bottomMargin">
</size> <number>9</number>
</property> </property>
</spacer> <item row="0" column="0" colspan="4">
</item> <layout class="QGridLayout" name="topGLayout">
<item row="0" column="1">
<widget class="QLabel" name="rsTopLogo">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>85</red>
<green>170</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>85</red>
<green>170</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>118</red>
<green>116</green>
<blue>108</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="font">
<font>
<pointsize>18</pointsize>
</font>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="images.qrc">:/images/logo/logo_spash2.png</pixmap>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>48</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="1" column="2" rowspan="2">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>60</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="0" colspan="3">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" rowspan="2">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>60</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="1">
<widget class="QGroupBox" name="profilGBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="title">
<string/>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<property name="leftMargin"> <property name="leftMargin">
<number>9</number> <number>16</number>
</property> </property>
<property name="topMargin">
<number>16</number>
</property>
<property name="rightMargin">
<number>16</number>
</property>
<property name="bottomMargin">
<number>16</number>
</property>
<item row="0" column="0">
<spacer name="topLHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QLabel" name="label_8"> <widget class="QLabel" name="rsTopLogo">
<property name="text"> <property name="minimumSize">
<string>Profile - Location:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_9">
<property name="maximumSize">
<size> <size>
<width>22</width> <width>0</width>
<height>22</height> <height>0</height>
</size> </size>
</property> </property>
<property name="text"> <property name="palette">
<string/> <palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>85</red>
<green>170</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>85</red>
<green>170</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>118</red>
<green>116</green>
<blue>108</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property> </property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/person.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="loadName"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_11">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/password.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="password_input">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
<property name="placeholderText">
<string>Password</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="autologin_checkbox">
<property name="text">
<string>Remember Password</string>
</property>
<property name="tristate">
<bool>false</bool>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="loadButton">
<property name="font"> <property name="font">
<font> <font>
<pointsize>12</pointsize> <pointsize>18</pointsize>
</font> </font>
</property> </property>
<property name="text"> <property name="text">
<string>Log In</string> <string/>
</property> </property>
<property name="default"> <property name="pixmap">
<bool>true</bool> <pixmap resource="images.qrc">:/images/logo/logo_web_nobackground.png</pixmap>
</property> </property>
<property name="flat"> </widget>
<bool>false</bool> </item>
<item row="0" column="2">
<spacer name="topRHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="1" column="2" rowspan="2">
<spacer name="profileRHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="0" colspan="3">
<spacer name="mainVSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" rowspan="2">
<spacer name="profileLHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="1">
<widget class="QGroupBox" name="profilGBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="title">
<string/>
</property>
<layout class="QGridLayout" name="profilGBoxGLayout">
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item row="1" column="0">
<widget class="QLabel" name="loadName_label">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/person.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="loadName"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="password_label">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/password.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="password_input">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
<property name="placeholderText">
<string>Password</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="autologin_checkbox">
<property name="text">
<string>Remember Password</string>
</property>
<property name="tristate">
<bool>false</bool>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="loadButton">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>Log In</string>
</property>
<property name="default">
<bool>true</bool>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="newHLayout">
<item>
<spacer name="newHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="labelProfile">
<property name="toolTip">
<string>Opens a dialog for creating a new profile or
adding locations to an existing profile.
The current identities/locations will not be affected.</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;Create new Profile...&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;&quot;&gt;New Profile/Node&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
</widget> </widget>
</item> </item>
</layout> </layout>
</widget> </item>
</item> </layout>
<item row="3" column="1"> </widget>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="labelProfile">
<property name="toolTip">
<string>Opens a dialog for creating a new profile or
adding locations to an existing profile.
The current identities/locations will not be affected.</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;Create new Profile...&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;&quot;&gt;Manage profiles and nodes...&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item> </item>
</layout> </layout>
</widget> </widget>

View file

@ -73,7 +73,7 @@
*****/ *****/
ChatWidget::ChatWidget(QWidget *parent) : ChatWidget::ChatWidget(QWidget *parent) :
QWidget(parent), ui(new Ui::ChatWidget) QWidget(parent), sendingBlocked(false), ui(new Ui::ChatWidget)
{ {
ui->setupUi(this); ui->setupUi(this);
@ -416,9 +416,20 @@ ChatWidget::ChatType ChatWidget::chatType()
return CHATTYPE_UNKNOWN; return CHATTYPE_UNKNOWN;
} }
void ChatWidget::blockSending(QString msg) { ui->sendButton->setToolTip(msg); } void ChatWidget::blockSending(QString msg)
{
#ifndef RS_ASYNC_CHAT
sendingBlocked = true;
ui->sendButton->setEnabled(false);
#endif
ui->sendButton->setToolTip(msg);
}
void ChatWidget::unblockSending() { updateLenOfChatTextEdit(); } void ChatWidget::unblockSending()
{
sendingBlocked = false;
updateLenOfChatTextEdit();
}
void ChatWidget::processSettings(bool load) void ChatWidget::processSettings(bool load)
{ {
@ -1130,6 +1141,8 @@ void ChatWidget::updateStatusTyping()
void ChatWidget::updateLenOfChatTextEdit() void ChatWidget::updateLenOfChatTextEdit()
{ {
if(sendingBlocked) return;
QTextEdit *chatWidget = ui->chatTextEdit; QTextEdit *chatWidget = ui->chatTextEdit;
QString text; QString text;
RsHtml::optimizeHtml(chatWidget, text); RsHtml::optimizeHtml(chatWidget, text);
@ -1429,7 +1442,8 @@ void ChatWidget::colorChanged()
void ChatWidget::chooseFont() void ChatWidget::chooseFont()
{ {
bool ok; bool ok;
QFont font = QFontDialog::getFont(&ok, currentFont, this); //Use NULL as parent as with this QFontDialog don't take care of title nether options.
QFont font = QFontDialog::getFont(&ok, currentFont, NULL, tr("Choose your font."),QFontDialog::DontUseNativeDialog);
if (ok) { if (ok) {
currentFont = font; currentFont = font;
setFont(); setFont();

View file

@ -36,7 +36,6 @@
#include <retroshare/rsmsgs.h> #include <retroshare/rsmsgs.h>
#include <retroshare/rsfiles.h> #include <retroshare/rsfiles.h>
#include <util/rsdeprecate.h>
class QAction; class QAction;
class QTextEdit; class QTextEdit;
@ -79,8 +78,9 @@ public:
ChatId getChatId(); ChatId getChatId();
ChatType chatType(); ChatType chatType();
RS_DEPRECATED void blockSending(QString msg); // allow/disallow sendng of messages
RS_DEPRECATED void unblockSending(); void blockSending(QString msg);
void unblockSending();
bool hasNewMessages() { return newMessages; } bool hasNewMessages() { return newMessages; }
bool isTyping() { return typing; } bool isTyping() { return typing; }
@ -216,6 +216,8 @@ private:
bool typing; bool typing;
int peerStatus; int peerStatus;
bool sendingBlocked;
time_t lastStatusSendTime; time_t lastStatusSendTime;
ChatStyle chatStyle; ChatStyle chatStyle;

View file

@ -37,7 +37,7 @@ public:
virtual QScrollArea *getScrollArea() = 0; virtual QScrollArea *getScrollArea() = 0;
virtual void deleteFeedItem(QWidget *item, uint32_t type) = 0; virtual void deleteFeedItem(QWidget *item, uint32_t type) = 0;
virtual void openChat(const RsPeerId& peerId) = 0; virtual void openChat(const RsPeerId& peerId) = 0;
virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, const QString &title) = 0; virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const QVector<RsGxsMessageId> &msg_versions, const RsGxsMessageId &msgId, const QString &title)=0;
// Workaround for QTBUG-3372 // Workaround for QTBUG-3372
void lockLayout(QWidget *feedItem, bool lock); void lockLayout(QWidget *feedItem, bool lock);

View file

@ -35,6 +35,7 @@
#include "util/HandleRichText.h" #include "util/HandleRichText.h"
#include "util/DateTime.h" #include "util/DateTime.h"
#include "util/stringutil.h" #include "util/stringutil.h"
#include "gui/gxschannels/CreateGxsChannelMsg.h"
#include <iostream> #include <iostream>
@ -63,9 +64,25 @@ GxsChannelPostItem::GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId,
std::cerr << std::endl; std::cerr << std::endl;
#endif #endif
QVector<RsGxsMessageId> v;
bool self = false;
for(std::set<RsGxsMessageId>::const_iterator it(post.mOlderVersions.begin());it!=post.mOlderVersions.end();++it)
{
if(*it == post.mMeta.mMsgId)
self = true ;
v.push_back(*it) ;
}
if(!self)
v.push_back(post.mMeta.mMsgId);
setMessageVersions(v) ;
setup(); setup();
setGroup(group, false); //setGroup(group, false);
requestGroup();
setPost(post); setPost(post);
requestComment(); requestComment();
} }
@ -127,6 +144,7 @@ void GxsChannelPostItem::setup()
connect(ui->commentButton, SIGNAL(clicked()), this, SLOT(loadComments())); connect(ui->commentButton, SIGNAL(clicked()), this, SLOT(loadComments()));
connect(ui->playButton, SIGNAL(clicked()), this, SLOT(play(void))); connect(ui->playButton, SIGNAL(clicked()), this, SLOT(play(void)));
connect(ui->editButton, SIGNAL(clicked()), this, SLOT(edit(void)));
connect(ui->copyLinkButton, SIGNAL(clicked()), this, SLOT(copyMessageLink())); connect(ui->copyLinkButton, SIGNAL(clicked()), this, SLOT(copyMessageLink()));
connect(ui->readButton, SIGNAL(toggled(bool)), this, SLOT(readToggled(bool))); connect(ui->readButton, SIGNAL(toggled(bool)), this, SLOT(readToggled(bool)));
@ -166,6 +184,12 @@ bool GxsChannelPostItem::setGroup(const RsGxsChannelGroup &group, bool doFill)
mGroup = group; mGroup = group;
// if not publisher, hide the edit button. Without the publish key, there's no way to edit a message.
std::cerr << "Group subscribe flags = " << std::hex << mGroup.mMeta.mSubscribeFlags << std::dec << std::endl;
if(!IS_GROUP_PUBLISHER(mGroup.mMeta.mSubscribeFlags))
ui->editButton->hide();
if (doFill) { if (doFill) {
fill(); fill();
} }
@ -301,7 +325,7 @@ void GxsChannelPostItem::loadComment(const uint32_t &token)
if (comNb == 1) { if (comNb == 1) {
sComButText = sComButText.append("(1)"); sComButText = sComButText.append("(1)");
} else if (comNb > 1) { } else if (comNb > 1) {
sComButText = tr("Comments").append("(%1)").arg(comNb); sComButText = tr("Comments ").append("(%1)").arg(comNb);
} }
ui->commentButton->setText(sComButText); ui->commentButton->setText(sComButText);
} }
@ -690,6 +714,12 @@ void GxsChannelPostItem::download()
updateItem(); updateItem();
} }
void GxsChannelPostItem::edit()
{
CreateGxsChannelMsg *msgDialog = new CreateGxsChannelMsg(mGroup.mMeta.mGroupId,mPost.mMeta.mMsgId);
msgDialog->show();
}
void GxsChannelPostItem::play() void GxsChannelPostItem::play()
{ {
std::list<SubFileItem *>::iterator it; std::list<SubFileItem *>::iterator it;

View file

@ -78,6 +78,7 @@ private slots:
void readAndClearItem(); void readAndClearItem();
void download(); void download();
void play(); void play();
void edit();
void loadComments(); void loadComments();
void readToggled(bool checked); void readToggled(bool checked);

View file

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>840</width> <width>1052</width>
<height>180</height> <height>338</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="gxsChannelPostItem_GLayout"> <layout class="QGridLayout" name="gxsChannelPostItem_GLayout">
@ -332,6 +332,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="editButton">
<property name="text">
<string>Edit</string>
</property>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer"> <spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">

View file

@ -97,11 +97,12 @@ SubFileItem::SubFileItem(const RsFileHash &hash, const std::string &name, const
void SubFileItem::Setup() void SubFileItem::Setup()
{ {
connect( playButton, SIGNAL( clicked( void ) ), this, SLOT( play ( void ) ) ); connect( playButton, SIGNAL( clicked( ) ), this, SLOT( play ( ) ) );
connect( downloadButton, SIGNAL( clicked( void ) ), this, SLOT( download ( void ) ) ); connect( downloadButton, SIGNAL( clicked( ) ), this, SLOT( download ( ) ) );
connect( cancelButton, SIGNAL( clicked( void ) ), this, SLOT( cancel ( void ) ) ); connect( cancelButton, SIGNAL( clicked( ) ), this, SLOT( cancel( ) ) );
connect( copyLinkButton, SIGNAL( clicked( void ) ), this, SLOT( copyLink ( void ) ) ); connect( deleteButton, SIGNAL( clicked( ) ), this, SLOT( del( ) ) );
connect( saveButton, SIGNAL( clicked( void ) ), this, SLOT( save ( void ) ) ); connect( copyLinkButton, SIGNAL( clicked( ) ), this, SLOT( copyLink ( ) ) );
connect( saveButton, SIGNAL( clicked( ) ), this, SLOT( save ( ) ) );
/* once off check - if remote, check if we have it /* once off check - if remote, check if we have it
* NB: This check might be expensive - and it'll happen often! * NB: This check might be expensive - and it'll happen often!
@ -129,12 +130,21 @@ void SubFileItem::Setup()
} }
} }
deleteButton->setVisible(mFlag & SFI_FLAG_ALLOW_DELETE);
downloadButton->setVisible(mMode < SFI_STATE_LOCAL);
cancelButton->setVisible(mMode < SFI_STATE_LOCAL);
smaller(); smaller();
updateItemStatic(); updateItemStatic();
updateItem(); updateItem();
} }
void SubFileItem::del()
{
emit wantsToBeDeleted();
}
bool SubFileItem::done() bool SubFileItem::done()
{ {
return (mMode >= SFI_STATE_LOCAL); return (mMode >= SFI_STATE_LOCAL);
@ -176,7 +186,7 @@ void SubFileItem::updateItemStatic()
} }
/* get full path for local file */ /* get full path for local file */
if ((mMode == SFI_STATE_LOCAL) || (mMode == SFI_STATE_UPLOAD)) if (((mMode == SFI_STATE_LOCAL) || (mMode == SFI_STATE_UPLOAD)))
{ {
#ifdef DEBUG_ITEM #ifdef DEBUG_ITEM
std::cerr << "SubFileItem::updateItemStatic() STATE=Local/Upload checking path"; std::cerr << "SubFileItem::updateItemStatic() STATE=Local/Upload checking path";
@ -190,7 +200,10 @@ void SubFileItem::updateItemStatic()
/* look up path */ /* look up path */
if (!rsFiles->FileDetails(mFileHash, hintflags, fi)) if (!rsFiles->FileDetails(mFileHash, hintflags, fi))
{ {
mMode = SFI_STATE_ERROR; if(mFlag & SFI_FLAG_ASSUME_FILE_READY)
mMode = SFI_STATE_REMOTE;
else
mMode = SFI_STATE_ERROR;
#ifdef DEBUG_ITEM #ifdef DEBUG_ITEM
std::cerr << "SubFileItem::updateItemStatic() STATE=>Error No Details"; std::cerr << "SubFileItem::updateItemStatic() STATE=>Error No Details";
std::cerr << std::endl; std::cerr << std::endl;
@ -241,6 +254,7 @@ void SubFileItem::updateItemStatic()
case SFI_STATE_REMOTE: case SFI_STATE_REMOTE:
playButton->setEnabled(false); playButton->setEnabled(false);
downloadButton->setEnabled(true); downloadButton->setEnabled(true);
downloadButton->setVisible(true);
cancelButton->setEnabled(false); cancelButton->setEnabled(false);
progressBar->setValue(0); progressBar->setValue(0);

View file

@ -40,7 +40,9 @@ const uint32_t SFI_STATE_UPLOAD = 0x0006;
const uint32_t SFI_TYPE_CHANNEL = 0x0010; const uint32_t SFI_TYPE_CHANNEL = 0x0010;
const uint32_t SFI_TYPE_ATTACH = 0x0020; const uint32_t SFI_TYPE_ATTACH = 0x0020;
const uint32_t SFI_FLAG_CREATE = 0x1000; const uint32_t SFI_FLAG_CREATE = 0x1000;
const uint32_t SFI_FLAG_ALLOW_DELETE = 0x2000;
const uint32_t SFI_FLAG_ASSUME_FILE_READY = 0x4000;
//! This create a gui widget that allows users to access files shared by user //! This create a gui widget that allows users to access files shared by user
@ -86,10 +88,14 @@ private slots:
void toggle(); void toggle();
void cancel(); void cancel();
void del();
void save(); void save();
void updateItem(); void updateItem();
signals:
void wantsToBeDeleted();
private: private:
void Setup(); void Setup();

View file

@ -6,12 +6,21 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>464</width> <width>547</width>
<height>71</height> <height>128</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="gridLayout_4"> <layout class="QGridLayout" name="gridLayout_4">
<property name="margin"> <property name="leftMargin">
<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">
@ -26,27 +35,6 @@
<enum>QFrame::Sunken</enum> <enum>QFrame::Sunken</enum>
</property> </property>
<layout class="QGridLayout" name="gridLayout_2"> <layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="fileLabel">
<property name="font">
<font>
<weight>75</weight>
<italic>true</italic>
<bold>true</bold>
</font>
</property>
<property name="text">
<string notr="true">File Name</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0"> <item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>
@ -210,6 +198,41 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="deleteButton">
<property name="toolTip">
<string>Remove this item</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<normaloff>:/images/denied16.png</normaloff>:/images/denied16.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="fileLabel">
<property name="font">
<font>
<weight>75</weight>
<italic>true</italic>
<bold>true</bold>
</font>
</property>
<property name="text">
<string notr="true">File Name</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
</layout> </layout>

View file

@ -54,7 +54,7 @@ void GxsCommentContainer::setup()
ui.tabWidget->hideCloseButton(index); ui.tabWidget->hideCloseButton(index);
} }
void GxsCommentContainer::commentLoad(const RsGxsGroupId &grpId, const RsGxsMessageId &msgId, const QString &title) void GxsCommentContainer::commentLoad(const RsGxsGroupId &grpId, const std::set<RsGxsMessageId>& msg_versions,const RsGxsMessageId &msgId, const QString &title)
{ {
QString comments = title; QString comments = title;
if (title.length() > MAX_COMMENT_TITLE) if (title.length() > MAX_COMMENT_TITLE)
@ -68,7 +68,7 @@ void GxsCommentContainer::commentLoad(const RsGxsGroupId &grpId, const RsGxsMess
QWidget *commentHeader = createHeaderWidget(grpId, msgId); QWidget *commentHeader = createHeaderWidget(grpId, msgId);
commentDialog->setCommentHeader(commentHeader); commentDialog->setCommentHeader(commentHeader);
commentDialog->commentLoad(grpId, msgId); commentDialog->commentLoad(grpId, msg_versions, msgId);
ui.tabWidget->addTab(commentDialog, comments); ui.tabWidget->addTab(commentDialog, comments);
} }

View file

@ -40,7 +40,7 @@ public:
GxsCommentContainer(QWidget *parent = 0); GxsCommentContainer(QWidget *parent = 0);
void setup(); void setup();
void commentLoad(const RsGxsGroupId &grpId, const RsGxsMessageId &msgId, const QString &title); void commentLoad(const RsGxsGroupId &grpId, const std::set<RsGxsMessageId> &msg_versions, const RsGxsMessageId &msgId, const QString &title);
virtual GxsServiceDialog *createServiceDialog() = 0; virtual GxsServiceDialog *createServiceDialog() = 0;
virtual QString getServiceName() = 0; virtual QString getServiceName() = 0;
@ -67,9 +67,9 @@ public:
virtual ~GxsServiceDialog() { return; } virtual ~GxsServiceDialog() { return; }
void commentLoad(const RsGxsGroupId &grpId, const RsGxsMessageId &msgId, const QString &title) void commentLoad(const RsGxsGroupId &grpId, const std::set<RsGxsMessageId>& msg_versions,const RsGxsMessageId &msgId, const QString &title)
{ {
mContainer->commentLoad(grpId, msgId, title); mContainer->commentLoad(grpId, msg_versions,msgId, title);
} }
private: private:

View file

@ -59,20 +59,16 @@ GxsCommentDialog::~GxsCommentDialog()
delete(ui); delete(ui);
} }
void GxsCommentDialog::commentLoad(const RsGxsGroupId &grpId, const RsGxsMessageId &msgId) void GxsCommentDialog::commentLoad(const RsGxsGroupId &grpId, const std::set<RsGxsMessageId>& msg_versions,const RsGxsMessageId& most_recent_msgId)
{ {
std::cerr << "GxsCommentDialog::commentLoad(" << grpId << ", " << msgId << ")"; std::cerr << "GxsCommentDialog::commentLoad(" << grpId << ", most recent msg version: " << most_recent_msgId << ")";
std::cerr << std::endl; std::cerr << std::endl;
mGrpId = grpId; mGrpId = grpId;
mMsgId = msgId; mMostRecentMsgId = most_recent_msgId;
mMsgVersions = msg_versions;
RsGxsGrpMsgIdPair threadId; ui->treeWidget->requestComments(mGrpId,msg_versions,most_recent_msgId);
threadId.first = grpId;
threadId.second = msgId;
ui->treeWidget->requestComments(threadId);
} }
void GxsCommentDialog::refresh() void GxsCommentDialog::refresh()
@ -80,7 +76,7 @@ void GxsCommentDialog::refresh()
std::cerr << "GxsCommentDialog::refresh()"; std::cerr << "GxsCommentDialog::refresh()";
std::cerr << std::endl; std::cerr << std::endl;
commentLoad(mGrpId, mMsgId); commentLoad(mGrpId, mMsgVersions,mMostRecentMsgId);
} }
void GxsCommentDialog::idChooserReady() void GxsCommentDialog::idChooserReady()

View file

@ -39,10 +39,10 @@ public:
virtual ~GxsCommentDialog(); virtual ~GxsCommentDialog();
void setCommentHeader(QWidget *header); void setCommentHeader(QWidget *header);
void commentLoad(const RsGxsGroupId &grpId, const RsGxsMessageId &msgId); void commentLoad(const RsGxsGroupId &grpId, const std::set<RsGxsMessageId> &msg_versions, const RsGxsMessageId &most_recent_msgId);
RsGxsGroupId groupId() { return mGrpId; } RsGxsGroupId groupId() { return mGrpId; }
RsGxsMessageId messageId() { return mMsgId; } RsGxsMessageId messageId() { return mMostRecentMsgId; }
private slots: private slots:
void refresh(); void refresh();
@ -51,7 +51,8 @@ private slots:
private: private:
RsGxsGroupId mGrpId; RsGxsGroupId mGrpId;
RsGxsMessageId mMsgId; RsGxsMessageId mMostRecentMsgId;
std::set<RsGxsMessageId> mMsgVersions;
/* UI - from Designer */ /* UI - from Designer */
Ui::GxsCommentDialog *ui; Ui::GxsCommentDialog *ui;

View file

@ -22,8 +22,12 @@
*/ */
#include <QMimeData> #include <QMimeData>
#include <QTextDocument>
#include <QAbstractTextDocumentLayout>
#include <QApplication>
#include <QDateTime> #include <QDateTime>
#include <QMenu> #include <QMenu>
#include <QPainter>
#include "gui/common/RSElidedItemDelegate.h" #include "gui/common/RSElidedItemDelegate.h"
#include "gui/gxs/GxsCommentTreeWidget.h" #include "gui/gxs/GxsCommentTreeWidget.h"
@ -46,11 +50,73 @@
#define COMMENT_VOTE_ACK 0x001234 #define COMMENT_VOTE_ACK 0x001234
#define POST_CELL_SIZE_ROLE (Qt::UserRole+1)
#define POST_COLOR_ROLE (Qt::UserRole+2)
/* Images for context menu icons */ /* Images for context menu icons */
#define IMAGE_MESSAGE ":/images/folder-draft.png" #define IMAGE_MESSAGE ":/images/folder-draft.png"
#define IMAGE_VOTEUP ":/images/vote_up.png" #define IMAGE_VOTEUP ":/images/vote_up.png"
#define IMAGE_VOTEDOWN ":/images/vote_down.png" #define IMAGE_VOTEDOWN ":/images/vote_down.png"
// This class allows to draw the item using an appropriate size
class MultiLinesCommentDelegate: public QStyledItemDelegate
{
public:
MultiLinesCommentDelegate(QFontMetricsF f) : qf(f){}
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return index.data(POST_CELL_SIZE_ROLE).toSize() ;
}
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_ASSERT(index.isValid());
QStyleOptionViewItemV4 opt = option;
initStyleOption(&opt, index);
// disable default icon
opt.icon = QIcon();
opt.text = QString();
// draw default item
QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter, 0);
const QRect r = option.rect;
QTextDocument td ;
td.setHtml("<html>"+index.data(Qt::DisplayRole).toString()+"</html>");
QSizeF s = td.documentLayout()->documentSize();
int m = QFontMetricsF(QFont()).height();
QSize full_area(std::min(r.width(),(int)s.width())+m,std::min(r.height(),(int)s.height())+m);
QPixmap px(full_area.width(),full_area.height());
px.fill();
QPainter p(&px) ;
p.setRenderHint(QPainter::Antialiasing);
QPainterPath path ;
path.addRoundedRect(QRectF(m/4.0,m/4.0,s.width()+m/2.0,s.height()+m/2.0),m,m) ;
QPen pen(Qt::gray,m/7.0f);
p.setPen(pen);
p.fillPath(path,QColor::fromHsv( index.data(POST_COLOR_ROLE).toInt()/255.0*360,40,220)); // varies the color according to the post author
p.drawPath(path);
QAbstractTextDocumentLayout::PaintContext ctx;
ctx.clip = QRectF(0,0,s.width(),s.height());
p.translate(QPointF(m/2.0,m/2.0));
td.documentLayout()->draw( &p, ctx );
painter->drawPixmap(r.topLeft(),px);
const_cast<QAbstractItemModel*>(index.model())->setData(index,px.size(),POST_CELL_SIZE_ROLE);
}
private:
QFontMetricsF qf;
};
GxsCommentTreeWidget::GxsCommentTreeWidget(QWidget *parent) GxsCommentTreeWidget::GxsCommentTreeWidget(QWidget *parent)
:QTreeWidget(parent), mTokenQueue(NULL), mRsTokenService(NULL), mCommentService(NULL) :QTreeWidget(parent), mTokenQueue(NULL), mRsTokenService(NULL), mCommentService(NULL)
@ -62,6 +128,9 @@ GxsCommentTreeWidget::GxsCommentTreeWidget(QWidget *parent)
itemDelegate->setSpacing(QSize(0, 2)); itemDelegate->setSpacing(QSize(0, 2));
setItemDelegate(itemDelegate); setItemDelegate(itemDelegate);
setWordWrap(true); setWordWrap(true);
setItemDelegateForColumn(PCITEM_COLUMN_COMMENT,new MultiLinesCommentDelegate(QFontMetricsF(font()))) ;
// QFont font = QFont("ARIAL", 10); // QFont font = QFont("ARIAL", 10);
// font.setBold(true); // font.setBold(true);
@ -85,14 +154,14 @@ GxsCommentTreeWidget::~GxsCommentTreeWidget()
} }
} }
void GxsCommentTreeWidget::setCurrentMsgId(QTreeWidgetItem *current, QTreeWidgetItem *previous) void GxsCommentTreeWidget::setCurrentCommentMsgId(QTreeWidgetItem *current, QTreeWidgetItem *previous)
{ {
Q_UNUSED(previous); Q_UNUSED(previous);
if(current) if(current)
{ {
mCurrentMsgId = RsGxsMessageId(current->text(PCITEM_COLUMN_MSGID).toStdString()); mCurrentCommentMsgId = RsGxsMessageId(current->text(PCITEM_COLUMN_MSGID).toStdString());
} }
} }
@ -100,9 +169,9 @@ void GxsCommentTreeWidget::customPopUpMenu(const QPoint& /*point*/)
{ {
QMenu contextMnu( this ); QMenu contextMnu( this );
QAction* action = contextMnu.addAction(QIcon(IMAGE_MESSAGE), tr("Reply to Comment"), this, SLOT(replyToComment())); QAction* action = contextMnu.addAction(QIcon(IMAGE_MESSAGE), tr("Reply to Comment"), this, SLOT(replyToComment()));
action->setDisabled(mCurrentMsgId.isNull()); action->setDisabled(mCurrentCommentMsgId.isNull());
action = contextMnu.addAction(QIcon(IMAGE_MESSAGE), tr("Submit Comment"), this, SLOT(makeComment())); action = contextMnu.addAction(QIcon(IMAGE_MESSAGE), tr("Submit Comment"), this, SLOT(makeComment()));
action->setDisabled(mThreadId.first.isNull()); action->setDisabled(mMsgVersions.empty());
contextMnu.addSeparator(); contextMnu.addSeparator();
@ -112,7 +181,7 @@ void GxsCommentTreeWidget::customPopUpMenu(const QPoint& /*point*/)
action->setDisabled(mVoterId.isNull()); action->setDisabled(mVoterId.isNull());
if (!mCurrentMsgId.isNull()) if (!mCurrentCommentMsgId.isNull())
{ {
// not implemented yet // not implemented yet
/* /*
@ -138,7 +207,8 @@ void GxsCommentTreeWidget::voteUp()
{ {
std::cerr << "GxsCommentTreeWidget::voteUp()"; std::cerr << "GxsCommentTreeWidget::voteUp()";
std::cerr << std::endl; std::cerr << std::endl;
vote(mThreadId.first, mThreadId.second, mCurrentMsgId, mVoterId, true);
vote(mGroupId, mLatestMsgId, mCurrentCommentMsgId, mVoterId, true);
} }
@ -146,7 +216,8 @@ void GxsCommentTreeWidget::voteDown()
{ {
std::cerr << "GxsCommentTreeWidget::voteDown()"; std::cerr << "GxsCommentTreeWidget::voteDown()";
std::cerr << std::endl; std::cerr << std::endl;
vote(mThreadId.first, mThreadId.second, mCurrentMsgId, mVoterId, false);
vote(mGroupId, mLatestMsgId, mCurrentCommentMsgId, mVoterId, false);
} }
void GxsCommentTreeWidget::setVoteId(const RsGxsId &voterId) void GxsCommentTreeWidget::setVoteId(const RsGxsId &voterId)
@ -216,16 +287,16 @@ void GxsCommentTreeWidget::banUser()
void GxsCommentTreeWidget::makeComment() void GxsCommentTreeWidget::makeComment()
{ {
GxsCreateCommentDialog pcc(mTokenQueue, mCommentService, mThreadId, mThreadId.second, this); GxsCreateCommentDialog pcc(mTokenQueue, mCommentService, std::make_pair(mGroupId,mLatestMsgId), mLatestMsgId, this);
pcc.exec(); pcc.exec();
} }
void GxsCommentTreeWidget::replyToComment() void GxsCommentTreeWidget::replyToComment()
{ {
RsGxsGrpMsgIdPair msgId; RsGxsGrpMsgIdPair msgId;
msgId.first = mThreadId.first; msgId.first = mGroupId;
msgId.second = mCurrentMsgId; msgId.second = mCurrentCommentMsgId;
GxsCreateCommentDialog pcc(mTokenQueue, mCommentService, msgId, mThreadId.second, this); GxsCreateCommentDialog pcc(mTokenQueue, mCommentService, msgId, mLatestMsgId, this);
pcc.exec(); pcc.exec();
} }
@ -235,36 +306,44 @@ void GxsCommentTreeWidget::setup(RsTokenService *token_service, RsGxsCommentServ
mCommentService = comment_service; mCommentService = comment_service;
mTokenQueue = new TokenQueue(token_service, this); mTokenQueue = new TokenQueue(token_service, this);
connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(customPopUpMenu(QPoint))); connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(customPopUpMenu(QPoint)));
connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(setCurrentMsgId(QTreeWidgetItem*, QTreeWidgetItem*))); connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(setCurrentCommentMsgId(QTreeWidgetItem*, QTreeWidgetItem*)));
return; return;
} }
/* Load Comments */ /* Load Comments */
void GxsCommentTreeWidget::requestComments(const RsGxsGrpMsgIdPair& threadId) void GxsCommentTreeWidget::requestComments(const RsGxsGroupId& group, const std::set<RsGxsMessageId>& message_versions,const RsGxsMessageId& most_recent_message)
{ {
/* request comments */ /* request comments */
mThreadId = threadId; mGroupId = group ;
service_requestComments(threadId); mMsgVersions = message_versions ;
mLatestMsgId = most_recent_message;
service_requestComments(group,message_versions);
} }
void GxsCommentTreeWidget::service_requestComments(const RsGxsGrpMsgIdPair& threadId) void GxsCommentTreeWidget::service_requestComments(const RsGxsGroupId& group_id,const std::set<RsGxsMessageId> & msgIds)
{ {
/* request comments */ /* request comments */
std::cerr << "GxsCommentTreeWidget::service_requestComments(" << threadId.second << ")"; std::cerr << "GxsCommentTreeWidget::service_requestComments for group " << group_id << std::endl;
std::cerr << std::endl;
std::vector<RsGxsGrpMsgIdPair> ids_to_ask;
for(std::set<RsGxsMessageId>::const_iterator it(msgIds.begin());it!=msgIds.end();++it)
{
std::cerr << " asking for msg " << *it << std::endl;
ids_to_ask.push_back(std::make_pair(group_id,*it));
}
RsTokReqOptions opts; RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA; opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA;
opts.mOptions = RS_TOKREQOPT_MSG_THREAD | RS_TOKREQOPT_MSG_LATEST; opts.mOptions = RS_TOKREQOPT_MSG_THREAD | RS_TOKREQOPT_MSG_LATEST;
std::vector<RsGxsGrpMsgIdPair> msgIds;
msgIds.push_back(threadId);
uint32_t token; uint32_t token;
mTokenQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, GXSCOMMENTS_LOADTHREAD); mTokenQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, ids_to_ask, GXSCOMMENTS_LOADTHREAD);
} }
@ -317,7 +396,7 @@ void GxsCommentTreeWidget::completeItems()
parent->addChild(pit->second); parent->addChild(pit->second);
} }
else if (parentId == mThreadId.second) else if (mMsgVersions.find(parentId) != mMsgVersions.end())
{ {
std::cerr << "GxsCommentTreeWidget::completeItems() Added to topLevelItems"; std::cerr << "GxsCommentTreeWidget::completeItems() Added to topLevelItems";
std::cerr << std::endl; std::cerr << std::endl;
@ -391,7 +470,7 @@ void GxsCommentTreeWidget::acknowledgeComment(const uint32_t &token)
mCommentService->acknowledgeComment(token, msgId); mCommentService->acknowledgeComment(token, msgId);
// simply reload data // simply reload data
service_requestComments(mThreadId); service_requestComments(mGroupId,mMsgVersions);
} }
@ -401,7 +480,7 @@ void GxsCommentTreeWidget::acknowledgeVote(const uint32_t &token)
if (mCommentService->acknowledgeVote(token, msgId)) if (mCommentService->acknowledgeVote(token, msgId))
{ {
// reload data if vote was added. // reload data if vote was added.
service_requestComments(mThreadId); service_requestComments(mGroupId,mMsgVersions);
} }
} }
@ -441,6 +520,7 @@ void GxsCommentTreeWidget::service_loadThread(const uint32_t &token)
RsGxsId authorId = comment.mMeta.mAuthorId; RsGxsId authorId = comment.mMeta.mAuthorId;
item->setId(authorId, PCITEM_COLUMN_AUTHOR, false); item->setId(authorId, PCITEM_COLUMN_AUTHOR, false);
item->setData(PCITEM_COLUMN_COMMENT,POST_COLOR_ROLE,QVariant(authorId.toByteArray()[1]));
text = QString::number(comment.mScore); text = QString::number(comment.mScore);
item->setText(PCITEM_COLUMN_SCORE, text); item->setText(PCITEM_COLUMN_SCORE, text);

View file

@ -39,7 +39,7 @@ public:
~GxsCommentTreeWidget(); ~GxsCommentTreeWidget();
void setup(RsTokenService *token_service, RsGxsCommentService *comment_service); void setup(RsTokenService *token_service, RsGxsCommentService *comment_service);
void requestComments(const RsGxsGrpMsgIdPair& threadId); void requestComments(const RsGxsGroupId& group, const std::set<RsGxsMessageId> &message_versions, const RsGxsMessageId &most_recent_message);
void getCurrentMsgId(RsGxsMessageId& parentId); void getCurrentMsgId(RsGxsMessageId& parentId);
void applyRankings(std::map<RsGxsMessageId, uint32_t>& positions); void applyRankings(std::map<RsGxsMessageId, uint32_t>& positions);
@ -49,7 +49,7 @@ public:
protected: protected:
/* to be overloaded */ /* to be overloaded */
virtual void service_requestComments(const RsGxsGrpMsgIdPair& threadId); virtual void service_requestComments(const RsGxsGroupId &group_id, const std::set<RsGxsMessageId> &msgIds);
virtual void service_loadThread(const uint32_t &token); virtual void service_loadThread(const uint32_t &token);
virtual QTreeWidgetItem *service_createMissingItem(const RsGxsMessageId& parent); virtual QTreeWidgetItem *service_createMissingItem(const RsGxsMessageId& parent);
@ -65,7 +65,7 @@ protected:
public slots: public slots:
void customPopUpMenu(const QPoint& point); void customPopUpMenu(const QPoint& point);
void setCurrentMsgId(QTreeWidgetItem* current, QTreeWidgetItem* previous); void setCurrentCommentMsgId(QTreeWidgetItem* current, QTreeWidgetItem* previous);
void makeComment(); void makeComment();
@ -85,8 +85,10 @@ protected:
const RsGxsMessageId &parentId, const RsGxsId &authorId, bool up); const RsGxsMessageId &parentId, const RsGxsId &authorId, bool up);
/* Data */ /* Data */
RsGxsGrpMsgIdPair mThreadId; RsGxsGroupId mGroupId;
RsGxsMessageId mCurrentMsgId; std::set<RsGxsMessageId> mMsgVersions;
RsGxsMessageId mLatestMsgId;
RsGxsMessageId mCurrentCommentMsgId;
RsGxsId mVoterId; RsGxsId mVoterId;
std::map<RsGxsMessageId, QTreeWidgetItem *> mLoadingMap; std::map<RsGxsMessageId, QTreeWidgetItem *> mLoadingMap;

View file

@ -64,7 +64,10 @@ void GxsFeedItem::comments(const QString &title)
if (mFeedHolder) if (mFeedHolder)
{ {
mFeedHolder->openComments(feedId(), groupId(), messageId(), title); if(mMessageVersions.empty())
mFeedHolder->openComments(feedId(), groupId(),QVector<RsGxsMessageId>(1,messageId()), messageId(), title);
else
mFeedHolder->openComments(feedId(), groupId(),mMessageVersions, messageId(), title);
} }
} }
@ -153,12 +156,12 @@ void GxsFeedItem::requestComment()
opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA; opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA;
opts.mOptions = RS_TOKREQOPT_MSG_THREAD | RS_TOKREQOPT_MSG_LATEST; opts.mOptions = RS_TOKREQOPT_MSG_THREAD | RS_TOKREQOPT_MSG_LATEST;
RsGxsGrpMsgIdPair msgIdPair;
msgIdPair.first = groupId();
msgIdPair.second = messageId();
std::vector<RsGxsGrpMsgIdPair> msgIds; std::vector<RsGxsGrpMsgIdPair> msgIds;
msgIds.push_back(msgIdPair);
for(uint32_t i=0;i<mMessageVersions.size();++i)
msgIds.push_back(std::make_pair(groupId(),mMessageVersions[i]));
msgIds.push_back(std::make_pair(groupId(),messageId()));
uint32_t token; uint32_t token;
mLoadQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, mTokenTypeComment); mLoadQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, mTokenTypeComment);

View file

@ -35,9 +35,12 @@ public:
GxsFeedItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, RsGxsIfaceHelper *iface, bool autoUpdate); GxsFeedItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, RsGxsIfaceHelper *iface, bool autoUpdate);
virtual ~GxsFeedItem(); virtual ~GxsFeedItem();
RsGxsMessageId messageId() { return mMessageId; } RsGxsMessageId messageId() const { return mMessageId; }
const QVector<RsGxsMessageId>& messageVersions() const { return mMessageVersions ; }
//To be able to update with thread message when comment is received. //To be able to update with thread message when comment is received.
void setMessageId( RsGxsMessageId id) {mMessageId = id;} void setMessageId( RsGxsMessageId id) {mMessageId = id;}
void setMessageVersions( const QVector<RsGxsMessageId>& v) { mMessageVersions = v;}
protected: protected:
/* load message data */ /* load message data */
@ -61,6 +64,7 @@ protected slots:
private: private:
RsGxsMessageId mMessageId; RsGxsMessageId mMessageId;
QVector<RsGxsMessageId> mMessageVersions ;
uint32_t mTokenTypeMessage; uint32_t mTokenTypeMessage;
uint32_t mTokenTypeComment; uint32_t mTokenTypeComment;
}; };

View file

@ -45,8 +45,8 @@ public:
GxsGroupFeedItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, bool isHome, RsGxsIfaceHelper *iface, bool autoUpdate); GxsGroupFeedItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, bool isHome, RsGxsIfaceHelper *iface, bool autoUpdate);
virtual ~GxsGroupFeedItem(); virtual ~GxsGroupFeedItem();
RsGxsGroupId groupId() { return mGroupId; } RsGxsGroupId groupId() const { return mGroupId; }
uint32_t feedId() { return mFeedId; } uint32_t feedId() const { return mFeedId; }
protected: protected:
uint32_t nextTokenType() { return ++mNextTokenType; } uint32_t nextTokenType() { return ++mNextTokenType; }

View file

@ -525,7 +525,7 @@ void GxsGroupFrameDialog::sharePublishKey()
shareUi.exec(); shareUi.exec();
} }
void GxsGroupFrameDialog::loadComment(const RsGxsGroupId &grpId, const RsGxsMessageId &msgId, const QString &title) void GxsGroupFrameDialog::loadComment(const RsGxsGroupId &grpId, const QVector<RsGxsMessageId>& msg_versions, const RsGxsMessageId &most_recent_msgId, const QString &title)
{ {
RsGxsCommentService *commentService = getCommentService(); RsGxsCommentService *commentService = getCommentService();
if (!commentService) { if (!commentService) {
@ -533,7 +533,8 @@ void GxsGroupFrameDialog::loadComment(const RsGxsGroupId &grpId, const RsGxsMess
return; return;
} }
GxsCommentDialog *commentDialog = commentWidget(msgId); GxsCommentDialog *commentDialog = commentWidget(most_recent_msgId);
if (!commentDialog) { if (!commentDialog) {
QString comments = title; QString comments = title;
if (title.length() > MAX_COMMENT_TITLE) if (title.length() > MAX_COMMENT_TITLE)
@ -544,12 +545,16 @@ void GxsGroupFrameDialog::loadComment(const RsGxsGroupId &grpId, const RsGxsMess
commentDialog = new GxsCommentDialog(this, mInterface->getTokenService(), commentService); commentDialog = new GxsCommentDialog(this, mInterface->getTokenService(), commentService);
QWidget *commentHeader = createCommentHeaderWidget(grpId, msgId); QWidget *commentHeader = createCommentHeaderWidget(grpId, most_recent_msgId);
if (commentHeader) { if (commentHeader) {
commentDialog->setCommentHeader(commentHeader); commentDialog->setCommentHeader(commentHeader);
} }
commentDialog->commentLoad(grpId, msgId); std::set<RsGxsMessageId> msgv;
for(int i=0;i<msg_versions.size();++i)
msgv.insert(msg_versions[i]);
commentDialog->commentLoad(grpId, msgv,most_recent_msgId);
int index = ui->messageTabWidget->addTab(commentDialog, comments); int index = ui->messageTabWidget->addTab(commentDialog, comments);
ui->messageTabWidget->setTabIcon(index, QIcon(IMAGE_COMMENT)); ui->messageTabWidget->setTabIcon(index, QIcon(IMAGE_COMMENT));
@ -620,12 +625,12 @@ GxsMessageFrameWidget *GxsGroupFrameDialog::createMessageWidget(const RsGxsGroup
connect(msgWidget, SIGNAL(groupChanged(QWidget*)), this, SLOT(messageTabInfoChanged(QWidget*))); connect(msgWidget, SIGNAL(groupChanged(QWidget*)), this, SLOT(messageTabInfoChanged(QWidget*)));
connect(msgWidget, SIGNAL(waitingChanged(QWidget*)), this, SLOT(messageTabWaitingChanged(QWidget*))); connect(msgWidget, SIGNAL(waitingChanged(QWidget*)), this, SLOT(messageTabWaitingChanged(QWidget*)));
connect(msgWidget, SIGNAL(loadComment(RsGxsGroupId,RsGxsMessageId,QString)), this, SLOT(loadComment(RsGxsGroupId,RsGxsMessageId,QString))); connect(msgWidget, SIGNAL(loadComment(RsGxsGroupId,QVector<RsGxsMessageId>,RsGxsMessageId,QString)), this, SLOT(loadComment(RsGxsGroupId,QVector<RsGxsMessageId>,RsGxsMessageId,QString)));
return msgWidget; return msgWidget;
} }
GxsCommentDialog *GxsGroupFrameDialog::commentWidget(const RsGxsMessageId &msgId) GxsCommentDialog *GxsGroupFrameDialog::commentWidget(const RsGxsMessageId& msgId)
{ {
int tabCount = ui->messageTabWidget->count(); int tabCount = ui->messageTabWidget->count();
for (int index = 0; index < tabCount; ++index) { for (int index = 0; index < tabCount; ++index) {

View file

@ -126,7 +126,7 @@ private slots:
void sharePublishKey(); void sharePublishKey();
void loadComment(const RsGxsGroupId &grpId, const RsGxsMessageId &msgId, const QString &title); void loadComment(const RsGxsGroupId &grpId, const QVector<RsGxsMessageId>& msg_versions,const RsGxsMessageId &most_recent_msgId, const QString &title);
private: private:
virtual QString text(TextType type) = 0; virtual QString text(TextType type) = 0;

View file

@ -54,7 +54,7 @@ public:
signals: signals:
void groupChanged(QWidget *widget); void groupChanged(QWidget *widget);
void waitingChanged(QWidget *widget); void waitingChanged(QWidget *widget);
void loadComment(const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, const QString &title); void loadComment(const RsGxsGroupId &groupId, const QVector<RsGxsMessageId>& msg_versions,const RsGxsMessageId &msgId, const QString &title);
protected: protected:
virtual void setAllMessagesReadDo(bool read, uint32_t &token) = 0; virtual void setAllMessagesReadDo(bool read, uint32_t &token) = 0;

View file

@ -38,11 +38,15 @@
//#define ENABLE_GENERATE //#define ENABLE_GENERATE
#define CREATEMSG_CHANNELINFO 0x002 #define CREATEMSG_CHANNELINFO 0x002
#define CREATEMSG_CHANNEL_POST_INFO 0x003
// #define DEBUG_CREATE_GXS_MSG
/** Constructor */ /** Constructor */
CreateGxsChannelMsg::CreateGxsChannelMsg(const RsGxsGroupId &cId) CreateGxsChannelMsg::CreateGxsChannelMsg(const RsGxsGroupId &cId, RsGxsMessageId existing_post)
: QDialog (NULL, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint), mChannelId(cId) ,mCheckAttachment(true), mAutoMediaThumbNail(false) : QDialog (NULL, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint),
mChannelId(cId) , mOrigPostId(existing_post),mCheckAttachment(true), mAutoMediaThumbNail(false)
{ {
/* Invoke the Qt Designer generated object setup routine */ /* Invoke the Qt Designer generated object setup routine */
setupUi(this); setupUi(this);
@ -50,7 +54,11 @@ CreateGxsChannelMsg::CreateGxsChannelMsg(const RsGxsGroupId &cId)
mChannelQueue = new TokenQueue(rsGxsChannels->getTokenService(), this); mChannelQueue = new TokenQueue(rsGxsChannels->getTokenService(), this);
headerFrame->setHeaderImage(QPixmap(":/images/channels.png")); headerFrame->setHeaderImage(QPixmap(":/images/channels.png"));
headerFrame->setHeaderText(tr("New Channel Post"));
if(!existing_post.isNull())
headerFrame->setHeaderText(tr("Edit Channel Post"));
else
headerFrame->setHeaderText(tr("New Channel Post"));
setAttribute ( Qt::WA_DeleteOnClose, true ); setAttribute ( Qt::WA_DeleteOnClose, true );
@ -337,43 +345,63 @@ void CreateGxsChannelMsg::parseRsFileListAttachments(const std::string &attachLi
} }
void CreateGxsChannelMsg::addAttachment(const RsFileHash &hash, const std::string &fname, uint64_t size, bool local, const RsPeerId &srcId) void CreateGxsChannelMsg::addAttachment(const RsFileHash &hash, const std::string &fname, uint64_t size, bool local, const RsPeerId &srcId, bool assume_file_ready)
{ {
/* add a SubFileItem to the attachment section */ /* add a SubFileItem to the attachment section */
#ifdef DEBUG_CREATE_GXS_MSG
std::cerr << "CreateGxsChannelMsg::addAttachment()"; std::cerr << "CreateGxsChannelMsg::addAttachment()";
std::cerr << std::endl; std::cerr << std::endl;
#endif
/* add widget in for new destination */ /* add widget in for new destination */
uint32_t flags = SFI_TYPE_CHANNEL; uint32_t flags = SFI_TYPE_CHANNEL | SFI_FLAG_ALLOW_DELETE ;
if(assume_file_ready)
flags |= SFI_FLAG_ASSUME_FILE_READY;
if (local) if (local)
{
flags |= SFI_STATE_LOCAL; flags |= SFI_STATE_LOCAL;
}
else else
{
flags |= SFI_STATE_REMOTE; flags |= SFI_STATE_REMOTE;
}
SubFileItem *file = new SubFileItem(hash, fname, "", size, flags, srcId); // destroyed when fileFrame (this subfileitem) is destroyed SubFileItem *file = new SubFileItem(hash, fname, "", size, flags, srcId); // destroyed when fileFrame (this subfileitem) is destroyed
connect(file,SIGNAL(wantsToBeDeleted()),this,SLOT(deleteAttachment())) ;
mAttachments.push_back(file); mAttachments.push_back(file);
QLayout *layout = fileFrame->layout(); QLayout *layout = fileFrame->layout();
layout->addWidget(file); layout->addWidget(file);
if (mCheckAttachment) if (mCheckAttachment)
{
checkAttachmentReady(); checkAttachmentReady();
} }
return; void CreateGxsChannelMsg::deleteAttachment()
{
// grab the item who sent the request
SubFileItem *file_item = qobject_cast<SubFileItem *>(QObject::sender());
for(std::list<SubFileItem*>::iterator it(mAttachments.begin());it!=mAttachments.end();)
if(*it == file_item)
{
SubFileItem *item = *it ;
it = mAttachments.erase(it) ;
fileFrame->layout()->removeWidget(file_item) ;
delete item ;
}
else
++it;
} }
void CreateGxsChannelMsg::addExtraFile() void CreateGxsChannelMsg::addExtraFile()
{ {
/* add a SubFileItem to the attachment section */ /* add a SubFileItem to the attachment section */
#ifdef DEBUG_CREATE_GXS_MSG
std::cerr << "CreateGxsChannelMsg::addExtraFile() opening file dialog"; std::cerr << "CreateGxsChannelMsg::addExtraFile() opening file dialog";
std::cerr << std::endl; std::cerr << std::endl;
#endif
QStringList files; QStringList files;
if (misc::getOpenFileNames(this, RshareSettings::LASTDIR_EXTRAFILE, tr("Add Extra File"), "", files)) { if (misc::getOpenFileNames(this, RshareSettings::LASTDIR_EXTRAFILE, tr("Add Extra File"), "", files)) {
@ -386,8 +414,10 @@ void CreateGxsChannelMsg::addExtraFile()
void CreateGxsChannelMsg::addAttachment(const std::string &path) void CreateGxsChannelMsg::addAttachment(const std::string &path)
{ {
/* add a SubFileItem to the attachment section */ /* add a SubFileItem to the attachment section */
#ifdef DEBUG_CREATE_GXS_MSG
std::cerr << "CreateGxsChannelMsg::addAttachment()"; std::cerr << "CreateGxsChannelMsg::addAttachment()";
std::cerr << std::endl; std::cerr << std::endl;
#endif
if(mAutoMediaThumbNail) if(mAutoMediaThumbNail)
setThumbNail(path, 2000); setThumbNail(path, 2000);
@ -522,8 +552,10 @@ void CreateGxsChannelMsg::checkAttachmentReady()
void CreateGxsChannelMsg::cancelMsg() void CreateGxsChannelMsg::cancelMsg()
{ {
#ifdef DEBUG_CREATE_GXS_MSG
std::cerr << "CreateGxsChannelMsg::cancelMsg() :" std::cerr << "CreateGxsChannelMsg::cancelMsg() :"
<< "Deleting EXTRA attachments" << std::endl; << "Deleting EXTRA attachments" << std::endl;
#endif
std::cerr << std::endl; std::cerr << std::endl;
@ -555,6 +587,15 @@ void CreateGxsChannelMsg::newChannelMsg()
uint32_t token; uint32_t token;
mChannelQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, groupIds, CREATEMSG_CHANNELINFO); mChannelQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, groupIds, CREATEMSG_CHANNELINFO);
if(!mOrigPostId.isNull())
{
GxsMsgReq message_ids;
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
message_ids[mChannelId].push_back(mOrigPostId);
mChannelQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, message_ids, CREATEMSG_CHANNEL_POST_INFO);
}
} }
} }
@ -569,8 +610,10 @@ void CreateGxsChannelMsg::saveChannelInfo(const RsGroupMetaData &meta)
void CreateGxsChannelMsg::sendMsg() void CreateGxsChannelMsg::sendMsg()
{ {
#ifdef DEBUG_CREATE_GXS_MSG
std::cerr << "CreateGxsChannelMsg::sendMsg()"; std::cerr << "CreateGxsChannelMsg::sendMsg()";
std::cerr << std::endl; std::cerr << std::endl;
#endif
/* construct message bits */ /* construct message bits */
std::string subject = std::string(misc::removeNewLine(subjectEdit->text()).toUtf8()); std::string subject = std::string(misc::removeNewLine(subjectEdit->text()).toUtf8());
@ -628,6 +671,7 @@ void CreateGxsChannelMsg::sendMessage(const std::string &subject, const std::str
post.mMeta.mThreadId.clear() ; post.mMeta.mThreadId.clear() ;
post.mMeta.mMsgId.clear() ; post.mMeta.mMsgId.clear() ;
post.mMeta.mOrigMsgId = mOrigPostId;
post.mMeta.mMsgName = subject; post.mMeta.mMsgName = subject;
post.mMsg = msg; post.mMsg = msg;
post.mFiles = files; post.mFiles = files;
@ -686,10 +730,47 @@ void CreateGxsChannelMsg::addThumbnail()
thumbnail_label->setPixmap(picture); thumbnail_label->setPixmap(picture);
} }
void CreateGxsChannelMsg::loadChannelPostInfo(const uint32_t &token)
{
#ifdef DEBUG_CREATE_GXS_MSG
std::cerr << "CreateGxsChannelMsg::loadChannelPostInfo()";
std::cerr << std::endl;
#endif
std::vector<RsGxsChannelPost> posts;
rsGxsChannels->getPostData(token, posts);
if (posts.size() != 1)
{
std::cerr << "CreateGxsChannelMsg::loadChannelPostInfo() ERROR INVALID Number of posts in request" << std::endl;
return ;
}
// now populate the widget with the channel post data.
const RsGxsChannelPost& post = posts[0];
if(post.mMeta.mGroupId != mChannelId || post.mMeta.mMsgId != mOrigPostId)
{
std::cerr << "CreateGxsChannelMsg::loadChannelPostInfo() ERROR INVALID post ID or channel ID" << std::endl;
return ;
}
subjectEdit->setText(QString::fromUtf8(post.mMeta.mMsgName.c_str())) ;
msgEdit->setText(QString::fromUtf8(post.mMsg.c_str())) ;
for(std::list<RsGxsFile>::const_iterator it(post.mFiles.begin());it!=post.mFiles.end();++it)
addAttachment(it->mHash,it->mName,it->mSize,true,RsPeerId(),true);
picture.loadFromData(post.mThumbnail.mData,post.mThumbnail.mSize,"PNG");
thumbnail_label->setPixmap(picture);
}
void CreateGxsChannelMsg::loadChannelInfo(const uint32_t &token) void CreateGxsChannelMsg::loadChannelInfo(const uint32_t &token)
{ {
#ifdef DEBUG_CREATE_GXS_MSG
std::cerr << "CreateGxsChannelMsg::loadChannelInfo()"; std::cerr << "CreateGxsChannelMsg::loadChannelInfo()";
std::cerr << std::endl; std::cerr << std::endl;
#endif
std::list<RsGroupMetaData> groupInfo; std::list<RsGroupMetaData> groupInfo;
rsGxsChannels->getGroupSummary(token, groupInfo); rsGxsChannels->getGroupSummary(token, groupInfo);
@ -708,8 +789,10 @@ void CreateGxsChannelMsg::loadChannelInfo(const uint32_t &token)
void CreateGxsChannelMsg::loadRequest(const TokenQueue *queue, const TokenRequest &req) void CreateGxsChannelMsg::loadRequest(const TokenQueue *queue, const TokenRequest &req)
{ {
#ifdef DEBUG_CREATE_GXS_MSG
std::cerr << "CreateGxsChannelMsg::loadRequest() UserType: " << req.mUserType; std::cerr << "CreateGxsChannelMsg::loadRequest() UserType: " << req.mUserType;
std::cerr << std::endl; std::cerr << std::endl;
#endif
if (queue == mChannelQueue) if (queue == mChannelQueue)
{ {
@ -719,6 +802,9 @@ void CreateGxsChannelMsg::loadRequest(const TokenQueue *queue, const TokenReques
case CREATEMSG_CHANNELINFO: case CREATEMSG_CHANNELINFO:
loadChannelInfo(req.mToken); loadChannelInfo(req.mToken);
break; break;
case CREATEMSG_CHANNEL_POST_INFO:
loadChannelPostInfo(req.mToken);
break;
default: default:
std::cerr << "CreateGxsChannelMsg::loadRequest() UNKNOWN UserType "; std::cerr << "CreateGxsChannelMsg::loadRequest() UNKNOWN UserType ";
std::cerr << std::endl; std::cerr << std::endl;

View file

@ -38,13 +38,13 @@ class CreateGxsChannelMsg : public QDialog, public TokenResponse, private Ui::Cr
public: public:
/** Default Constructor */ /** Default Constructor */
CreateGxsChannelMsg(const RsGxsGroupId& cId); CreateGxsChannelMsg(const RsGxsGroupId& cId, RsGxsMessageId existing_post = RsGxsMessageId());
/** Default Destructor */ /** Default Destructor */
~CreateGxsChannelMsg(); ~CreateGxsChannelMsg();
void addAttachment(const std::string &path); void addAttachment(const std::string &path);
void addAttachment(const RsFileHash &hash, const std::string &fname, uint64_t size, bool local, const RsPeerId &srcId); void addAttachment(const RsFileHash &hash, const std::string &fname, uint64_t size, bool local, const RsPeerId &srcId,bool assume_file_ready = false);
void newChannelMsg(); void newChannelMsg();
@ -60,6 +60,7 @@ protected:
private slots: private slots:
void addExtraFile(); void addExtraFile();
void checkAttachmentReady(); void checkAttachmentReady();
void deleteAttachment();
void cancelMsg(); void cancelMsg();
void sendMsg(); void sendMsg();
@ -71,6 +72,7 @@ private slots:
private: private:
void loadChannelInfo(const uint32_t &token); void loadChannelInfo(const uint32_t &token);
void loadChannelPostInfo(const uint32_t &token);
void saveChannelInfo(const RsGroupMetaData &group); void saveChannelInfo(const RsGroupMetaData &group);
void parseRsFileListAttachments(const std::string &attachList); void parseRsFileListAttachments(const std::string &attachList);
@ -78,7 +80,9 @@ private:
bool setThumbNail(const std::string& path, int frame); bool setThumbNail(const std::string& path, int frame);
RsGxsGroupId mChannelId; RsGxsGroupId mChannelId;
RsGxsMessageId mOrigPostId;
RsGroupMetaData mChannelMeta; RsGroupMetaData mChannelMeta;
RsMsgMetaData mOrigMeta;
bool mChannelMetaLoaded; bool mChannelMetaLoaded;
std::list<SubFileItem *> mAttachments; std::list<SubFileItem *> mAttachments;

View file

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>581</width> <width>875</width>
<height>479</height> <height>659</height>
</rect> </rect>
</property> </property>
<property name="acceptDrops"> <property name="acceptDrops">
@ -60,7 +60,7 @@
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>1</number>
</property> </property>
<widget class="QWidget" name="channelPostTab"> <widget class="QWidget" name="channelPostTab">
<attribute name="title"> <attribute name="title">
@ -302,8 +302,8 @@ p, li { white-space: pre-wrap; }
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>523</width> <width>767</width>
<height>24</height> <height>42</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">

View file

@ -207,9 +207,9 @@ void GxsChannelPostsWidget::openChat(const RsPeerId & /*peerId*/)
} }
// Callback from Widget->FeedHolder->ServiceDialog->CommentContainer->CommentDialog, // Callback from Widget->FeedHolder->ServiceDialog->CommentContainer->CommentDialog,
void GxsChannelPostsWidget::openComments(uint32_t /*type*/, const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, const QString &title) void GxsChannelPostsWidget::openComments(uint32_t /*type*/, const RsGxsGroupId &groupId, const QVector<RsGxsMessageId>& msg_versions,const RsGxsMessageId &msgId, const QString &title)
{ {
emit loadComment(groupId, msgId, title); emit loadComment(groupId, msg_versions,msgId, title);
} }
void GxsChannelPostsWidget::createMsg() void GxsChannelPostsWidget::createMsg()
@ -398,7 +398,27 @@ void GxsChannelPostsWidget::filterChanged(int filter)
void GxsChannelPostsWidget::createPostItem(const RsGxsChannelPost &post, bool related) void GxsChannelPostsWidget::createPostItem(const RsGxsChannelPost &post, bool related)
{ {
GxsChannelPostItem *item = NULL; GxsChannelPostItem *item = NULL;
if (related) {
if(!post.mMeta.mOrigMsgId.isNull())
{
FeedItem *feedItem = ui->feedWidget->findGxsFeedItem(post.mMeta.mGroupId, post.mMeta.mOrigMsgId);
item = dynamic_cast<GxsChannelPostItem*>(feedItem);
if(item)
{
ui->feedWidget->removeFeedItem(item) ;
RsGxsChannelGroup dummyGroup;
dummyGroup.mMeta.mGroupId = groupId();
dummyGroup.mMeta.mSubscribeFlags = 0xffffffff;
GxsChannelPostItem *item = new GxsChannelPostItem(this, 0, dummyGroup, post, true, false);
ui->feedWidget->addFeedItem(item, ROLE_PUBLISH, QDateTime::fromTime_t(post.mMeta.mPublishTs));
return ;
}
}
if (related)
{
FeedItem *feedItem = ui->feedWidget->findGxsFeedItem(post.mMeta.mGroupId, post.mMeta.mMsgId); FeedItem *feedItem = ui->feedWidget->findGxsFeedItem(post.mMeta.mGroupId, post.mMeta.mMsgId);
item = dynamic_cast<GxsChannelPostItem*>(feedItem); item = dynamic_cast<GxsChannelPostItem*>(feedItem);
} }
@ -438,8 +458,6 @@ void GxsChannelPostsWidget::insertChannelPosts(std::vector<RsGxsChannelPost> &po
return; return;
} }
std::vector<RsGxsChannelPost>::const_reverse_iterator it;
int count = posts.size(); int count = posts.size();
int pos = 0; int pos = 0;
@ -447,18 +465,127 @@ void GxsChannelPostsWidget::insertChannelPosts(std::vector<RsGxsChannelPost> &po
ui->feedWidget->setSortingEnabled(false); ui->feedWidget->setSortingEnabled(false);
} }
for (it = posts.rbegin(); it != posts.rend(); ++it) // collect new versions of posts if any
{
if (thread && thread->stopped()) {
break;
}
if (thread) { #ifdef DEBUG_CHANNEL
thread->emitAddPost(qVariantFromValue(*it), related, ++pos, count); std::cerr << "Inserting channel posts" << std::endl;
} else { #endif
createPostItem(*it, related);
std::vector<uint32_t> new_versions ;
for (uint32_t i=0;i<posts.size();++i)
{
if(posts[i].mMeta.mOrigMsgId == posts[i].mMeta.mMsgId)
posts[i].mMeta.mOrigMsgId.clear();
#ifdef DEBUG_CHANNEL
std::cerr << " " << i << ": msg_id=" << posts[i].mMeta.mMsgId << ": orig msg id = " << posts[i].mMeta.mOrigMsgId << std::endl;
#endif
if(!posts[i].mMeta.mOrigMsgId.isNull())
new_versions.push_back(i) ;
}
#ifdef DEBUG_CHANNEL
std::cerr << "New versions: " << new_versions.size() << std::endl;
#endif
if(!new_versions.empty())
{
#ifdef DEBUG_CHANNEL
std::cerr << " New versions present. Replacing them..." << std::endl;
std::cerr << " Creating search map." << std::endl;
#endif
// make a quick search map
std::map<RsGxsMessageId,uint32_t> search_map ;
for (uint32_t i=0;i<posts.size();++i)
search_map[posts[i].mMeta.mMsgId] = i ;
for(uint32_t i=0;i<new_versions.size();++i)
{
#ifdef DEBUG_CHANNEL
std::cerr << " Taking care of new version at index " << new_versions[i] << std::endl;
#endif
uint32_t current_index = new_versions[i] ;
uint32_t source_index = new_versions[i] ;
RsGxsMessageId source_msg_id = posts[source_index].mMeta.mMsgId ;
// What we do is everytime we find a replacement post, we climb up the replacement graph until we find the original post
// (or the most recent version of it). When we reach this post, we replace it with the data of the source post.
// In the mean time, all other posts have their MsgId cleared, so that the posts are removed from the list.
std::vector<uint32_t> versions ;
std::map<RsGxsMessageId,uint32_t>::const_iterator vit ;
while(search_map.end() != (vit=search_map.find(posts[current_index].mMeta.mOrigMsgId)))
{
#ifdef DEBUG_CHANNEL
std::cerr << " post at index " << current_index << " replaces a post at position " << vit->second ;
#endif
// Now replace the post only if the new versionis more recent. It may happen indeed that the same post has been corrected multiple
// times. In this case, we only need to replace the post with the newest version
uint32_t prev_index = current_index ;
current_index = vit->second ;
if(posts[current_index].mMeta.mMsgId.isNull()) // This handles the branching situation where this post has been already erased. No need to go down further.
{
#ifdef DEBUG_CHANNEL
std::cerr << " already erased. Stopping." << std::endl;
#endif
break ;
}
if(posts[current_index].mMeta.mPublishTs < posts[source_index].mMeta.mPublishTs)
{
#ifdef DEBUG_CHANNEL
std::cerr << " and is more recent => following" << std::endl;
#endif
for(std::set<RsGxsMessageId>::const_iterator itt(posts[current_index].mOlderVersions.begin());itt!=posts[current_index].mOlderVersions.end();++itt)
posts[source_index].mOlderVersions.insert(*itt);
posts[source_index].mOlderVersions.insert(posts[current_index].mMeta.mMsgId);
posts[current_index].mMeta.mMsgId.clear(); // clear the msg Id so the post will be ignored
}
#ifdef DEBUG_CHANNEL
else
std::cerr << " but is older -> Stopping" << std::endl;
#endif
}
}
}
#ifdef DEBUG_CHANNEL
std::cerr << "Now adding posts..." << std::endl;
#endif
for (std::vector<RsGxsChannelPost>::const_reverse_iterator it = posts.rbegin(); it != posts.rend(); ++it)
{
#ifdef DEBUG_CHANNEL
std::cerr << " adding post: " << (*it).mMeta.mMsgId ;
#endif
if(!(*it).mMeta.mMsgId.isNull())
{
#ifdef DEBUG_CHANNEL
std::cerr << " added" << std::endl;
#endif
if (thread && thread->stopped())
break;
if (thread)
thread->emitAddPost(qVariantFromValue(*it), related, ++pos, count);
else
createPostItem(*it, related);
} }
} #ifdef DEBUG_CHANNEL
else
std::cerr << " skipped" << std::endl;
#endif
}
if (!thread) { if (!thread) {
ui->feedWidget->setSortingEnabled(true); ui->feedWidget->setSortingEnabled(true);

View file

@ -61,7 +61,7 @@ public:
virtual QScrollArea *getScrollArea(); virtual QScrollArea *getScrollArea();
virtual void deleteFeedItem(QWidget *item, uint32_t type); virtual void deleteFeedItem(QWidget *item, uint32_t type);
virtual void openChat(const RsPeerId& peerId); virtual void openChat(const RsPeerId& peerId);
virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, const QString &title); virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const QVector<RsGxsMessageId> &msg_versions, const RsGxsMessageId &msgId, const QString &title);
protected: protected:
/* GxsMessageFramePostWidget */ /* GxsMessageFramePostWidget */

View file

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>793</width> <width>880</width>
<height>465</height> <height>557</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
@ -454,7 +454,7 @@
<string notr="true">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt; <string notr="true">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt; &lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; } p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt; &lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt;&quot;&gt;Description&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt;&quot;&gt;Description&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="textInteractionFlags"> <property name="textInteractionFlags">

View file

@ -1,5 +1,7 @@
<RCC> <RCC>
<qresource prefix="/"> <qresource prefix="/">
<file>icons/svg/hidden.svg</file>
<file>icons/svg/randomness.svg</file>
<file>icons/svg/password.svg</file> <file>icons/svg/password.svg</file>
<file>icons/stars/star0.png</file> <file>icons/stars/star0.png</file>
<file>icons/stars/star1.png</file> <file>icons/stars/star1.png</file>
@ -11,6 +13,12 @@
<file>icons/anonymous_blue_128.png</file> <file>icons/anonymous_blue_128.png</file>
<file>icons/anonymous_green_128.png</file> <file>icons/anonymous_green_128.png</file>
<file>icons/aol.png</file> <file>icons/aol.png</file>
<file>icons/transport128.png</file>
<file>icons/bandwidth128.png</file>
<file>icons/RTT128.png</file>
<file>icons/DHT128.png</file>
<file>icons/turtle128.png</file>
<file>icons/GRouter128.png</file>
<file>icons/avatar_128.png</file> <file>icons/avatar_128.png</file>
<file>icons/avatar_grey_128.png</file> <file>icons/avatar_grey_128.png</file>
<file>icons/biohazard_red.png</file> <file>icons/biohazard_red.png</file>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View file

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg4155"
version="1.1"
inkscape:version="0.91 r13725"
xml:space="preserve"
width="80"
height="80"
viewBox="0 0 80 80"
sodipodi:docname="hidden.svg"><metadata
id="metadata4161"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs4159"><linearGradient
id="linearGradient5584"
osb:paint="solid"><stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop5586" /></linearGradient></defs><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1366"
inkscape:window-height="706"
id="namedview4157"
showgrid="false"
inkscape:zoom="3.6195029"
inkscape:cx="37.953819"
inkscape:cy="49.057609"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="g4163" /><g
id="g4163"
inkscape:groupmode="layer"
inkscape:label="ink_ext_XXXXXX"
transform="matrix(1.25,0,0,-1.25,0,80)"><path
inkscape:connector-curvature="0"
id="path4167"
style="fill:#039bd5;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 64,32 C 64,14.327 49.673,0 32,0 14.327,0 0,14.327 0,32 0,49.673 14.327,64 32,64 49.673,64 64,49.673 64,32" /><g
transform="matrix(0.47818792,0,0,-0.47818794,8.3042308,56.181608)"
id="g3"><g
id="g5"><path
style="fill:#ffffff"
inkscape:connector-curvature="0"
d="M 69.322,44.716 49.715,64.323 C 60.438,64.072 69.071,55.438 69.322,44.716 Z"
id="path7" /><path
style="fill:#ffffff"
inkscape:connector-curvature="0"
d="M 97.204,45.789 C 96.755,45.26 90.959,38.559 81.802,32.235 l -6.2,6.2 c 5.99,3.954 10.559,8.275 13.011,10.806 -5.378,5.554 -20.913,19.728 -39.372,19.728 -1.334,0 -2.651,-0.082 -3.952,-0.222 l -7.439,7.438 c 3.639,0.91 7.449,1.451 11.391,1.451 26.426,0 47.098,-23.927 47.964,-24.946 1.701,-1.998 1.701,-4.9 -0.001,-6.901 z"
id="path9" /><path
style="fill:#ffffff"
inkscape:connector-curvature="0"
d="m 90.651,15.901 c 0,-0.266 -0.104,-0.52 -0.293,-0.707 l -7.071,-7.07 c -0.391,-0.391 -1.022,-0.391 -1.414,0 L 66.045,23.952 C 60.843,22.059 55.19,20.844 49.241,20.844 22.814,20.844 2.143,44.77 1.276,45.79 c -1.701,2 -1.701,4.902 10e-4,6.903 0.517,0.606 8.083,9.354 19.707,16.319 l -12.86,12.86 c -0.188,0.188 -0.293,0.441 -0.293,0.707 0,0.267 0.105,0.521 0.293,0.707 l 7.071,7.07 c 0.195,0.194 0.451,0.293 0.707,0.293 0.256,0 0.512,-0.099 0.707,-0.293 l 73.75,-73.75 c 0.187,-0.185 0.292,-0.439 0.292,-0.705 z M 9.869,49.241 C 13.5,45.49 21.767,37.812 32.436,33.22 c -2.081,3.166 -3.301,6.949 -3.301,11.021 0,4.665 1.601,8.945 4.27,12.352 l -6.124,6.123 C 19.129,58.196 12.89,52.361 9.869,49.241 Z"
id="path11" /></g></g></g></svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View file

@ -0,0 +1,197 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg4155"
version="1.1"
inkscape:version="0.91 r13725"
xml:space="preserve"
width="80"
height="80"
viewBox="0 0 80 80"
sodipodi:docname="randomness.svg"><metadata
id="metadata4161"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs4159" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1366"
inkscape:window-height="706"
id="namedview4157"
showgrid="false"
inkscape:zoom="5.11875"
inkscape:cx="54.735476"
inkscape:cy="40.772004"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="g4163" /><g
id="g4163"
inkscape:groupmode="layer"
inkscape:label="ink_ext_XXXXXX"
transform="matrix(1.25,0,0,-1.25,0,80)"><path
inkscape:connector-curvature="0"
id="path4167"
style="fill:#039bd5;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 64,32 C 64,14.327 49.673,0 32,0 14.327,0 0,14.327 0,32 0,49.673 14.327,64 32,64 49.673,64 64,49.673 64,32" /><g
transform="matrix(1.4341283,-0.03685349,-0.03685349,-1.4341283,6.7291558,58.393566)"
id="g3"><g
id="g5"><polygon
style="fill:#ffffff"
points="11.78,8.598 7.526,6.141 7.526,11.054 "
id="polygon7" /><polygon
style="fill:#ffffff"
points="11.78,14.738 7.526,12.282 7.526,17.193 "
id="polygon9" /><polygon
style="fill:#ffffff"
points="11.78,27.02 7.526,24.562 7.526,29.475 "
id="polygon11" /><polygon
style="fill:#ffffff"
points="12.135,27.635 7.881,30.09 12.135,32.546 "
id="polygon13" /><polygon
style="fill:#ffffff"
points="12.135,15.352 7.881,17.809 12.135,20.266 "
id="polygon15" /><polygon
style="fill:#ffffff"
points="12.135,9.211 7.881,11.668 12.135,14.124 "
id="polygon17" /><polygon
style="fill:#ffffff"
points="12.135,3.071 7.881,5.527 12.135,7.983 "
id="polygon19" /><polygon
style="fill:#ffffff"
points="17.099,5.527 12.844,3.071 12.844,7.983 "
id="polygon21" /><polygon
style="fill:#ffffff"
points="17.099,11.668 12.844,9.211 12.844,14.124 "
id="polygon23" /><polygon
style="fill:#ffffff"
points="17.099,17.809 12.844,15.352 12.844,20.266 "
id="polygon25" /><polygon
style="fill:#ffffff"
points="17.099,23.949 12.844,21.493 12.844,26.405 "
id="polygon27" /><polygon
style="fill:#ffffff"
points="17.099,30.09 12.844,27.635 12.844,32.546 "
id="polygon29" /><polygon
style="fill:#ffffff"
points="17.453,30.704 13.199,33.16 17.453,35.616 "
id="polygon31" /><polygon
style="fill:#ffffff"
points="17.453,24.562 13.199,27.02 17.453,29.475 "
id="polygon33" /><polygon
style="fill:#ffffff"
points="17.453,18.422 13.199,20.879 17.453,23.335 "
id="polygon35" /><polygon
style="fill:#ffffff"
points="17.453,12.282 13.199,14.738 17.453,17.193 "
id="polygon37" /><polygon
style="fill:#ffffff"
points="17.453,0 13.199,2.456 17.453,4.913 "
id="polygon39" /><polygon
style="fill:#ffffff"
points="6.462,11.668 2.208,9.211 2.208,14.124 "
id="polygon41" /><polygon
style="fill:#ffffff"
points="6.462,17.809 2.208,15.352 2.208,20.266 "
id="polygon43" /><polygon
style="fill:#ffffff"
points="6.462,23.949 2.208,21.493 2.208,26.405 "
id="polygon45" /><polygon
style="fill:#ffffff"
points="6.817,24.562 2.562,27.02 6.817,29.475 "
id="polygon47" /><polygon
style="fill:#ffffff"
points="6.817,18.422 2.562,20.879 6.817,23.335 "
id="polygon49" /><polygon
style="fill:#ffffff"
points="6.817,12.282 2.562,14.738 6.817,17.193 "
id="polygon51" /><polygon
style="fill:#ffffff"
points="6.817,6.141 2.562,8.598 6.817,11.054 "
id="polygon53" /><polygon
style="fill:#ffffff"
points="22.416,2.456 18.162,0 18.162,4.913 "
id="polygon55" /><polygon
style="fill:#ffffff"
points="22.416,14.738 18.162,12.282 18.162,17.193 "
id="polygon57" /><polygon
style="fill:#ffffff"
points="22.416,20.879 18.162,18.422 18.162,23.335 "
id="polygon59" /><polygon
style="fill:#ffffff"
points="22.416,27.02 18.162,24.562 18.162,29.475 "
id="polygon61" /><polygon
style="fill:#ffffff"
points="22.416,33.16 18.162,30.704 18.162,35.616 "
id="polygon63" /><polygon
style="fill:#ffffff"
points="22.771,27.635 18.517,30.09 22.771,32.546 "
id="polygon65" /><polygon
style="fill:#ffffff"
points="22.771,21.493 18.517,23.949 22.771,26.405 "
id="polygon67" /><polygon
style="fill:#ffffff"
points="22.771,15.352 18.517,17.809 22.771,20.266 "
id="polygon69" /><polygon
style="fill:#ffffff"
points="22.771,9.211 18.517,11.668 22.771,14.124 "
id="polygon71" /><polygon
style="fill:#ffffff"
points="22.771,3.071 18.517,5.527 22.771,7.983 "
id="polygon73" /><polygon
style="fill:#ffffff"
points="27.735,5.527 23.479,3.071 23.479,7.983 "
id="polygon75" /><polygon
style="fill:#ffffff"
points="27.735,11.668 23.479,9.211 23.479,14.124 "
id="polygon77" /><polygon
style="fill:#ffffff"
points="27.735,17.809 23.479,15.352 23.479,20.266 "
id="polygon79" /><polygon
style="fill:#ffffff"
points="27.735,30.09 23.479,27.635 23.479,32.546 "
id="polygon81" /><polygon
style="fill:#ffffff"
points="28.089,24.562 23.835,27.02 28.089,29.475 "
id="polygon83" /><polygon
style="fill:#ffffff"
points="28.089,12.282 23.835,14.738 28.089,17.193 "
id="polygon85" /><polygon
style="fill:#ffffff"
points="28.089,6.141 23.835,8.598 28.089,11.054 "
id="polygon87" /><polygon
style="fill:#ffffff"
points="33.052,8.598 28.798,6.141 28.798,11.054 "
id="polygon89" /><polygon
style="fill:#ffffff"
points="33.052,14.738 28.798,12.282 28.798,17.193 "
id="polygon91" /><polygon
style="fill:#ffffff"
points="33.052,20.879 28.798,18.422 28.798,23.335 "
id="polygon93" /><polygon
style="fill:#ffffff"
points="33.052,27.02 28.798,24.562 28.798,29.475 "
id="polygon95" /><polygon
style="fill:#ffffff"
points="33.408,21.493 29.153,23.949 33.408,26.405 "
id="polygon97" /><polygon
style="fill:#ffffff"
points="33.408,15.352 29.153,17.809 33.408,20.266 "
id="polygon99" /><polygon
style="fill:#ffffff"
points="33.408,9.211 29.153,11.668 33.408,14.124 "
id="polygon101" /></g></g></g></svg>

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View file

@ -1,5 +1,7 @@
<RCC> <RCC>
<qresource prefix="/"> <qresource prefix="/">
<file>images/logo/background.png</file>
<file>images/logo/background_lessblue.png</file>
<file>images/logo/logo_spash2.png</file> <file>images/logo/logo_spash2.png</file>
<file>images/network_map.png</file> <file>images/network_map.png</file>
<file>images/global_switch_on.png</file> <file>images/global_switch_on.png</file>
@ -349,6 +351,7 @@
<file>images/logo/logo_512.png</file> <file>images/logo/logo_512.png</file>
<file>images/logo/logo_info.png</file> <file>images/logo/logo_info.png</file>
<file>images/logo/logo_splash.png</file> <file>images/logo/logo_splash.png</file>
<file>images/logo/logo_web_nobackground.png</file>
<file>images/logobar/logo_bar_fill.png</file> <file>images/logobar/logo_bar_fill.png</file>
<file>images/logobar/logo_bar_start.png</file> <file>images/logobar/logo_bar_start.png</file>
<file>images/logobar/rslogo.png</file> <file>images/logobar/rslogo.png</file>

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -0,0 +1,184 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="144.40031"
height="31.875484"
id="svg6043"
version="1.1"
inkscape:version="0.92.1 r"
viewBox="0 0 144.40032 31.875486"
sodipodi:docname="logo_web_nobackground.svg"
inkscape:export-filename="/home/phenom/GIT/RetroShare/trunk/retroshare-gui/src/gui/images/logo/logo_web_nobackground.png"
inkscape:export-xdpi="265.03128"
inkscape:export-ydpi="265.03128">
<defs
id="defs6045">
<linearGradient
id="linearGradient4183"
inkscape:collect="always">
<stop
id="stop4185"
offset="0"
style="stop-color:#abe3ff;stop-opacity:1" />
<stop
id="stop4187"
offset="1"
style="stop-color:#0e8ecb;stop-opacity:1" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4183"
id="linearGradient4170"
x1="-707.36493"
y1="878.20923"
x2="-694.01666"
y2="892.13776"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4183"
id="linearGradient4172"
gradientUnits="userSpaceOnUse"
x1="2.3214316"
y1="9.6272764"
x2="15.030971"
y2="22.573706" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4183"
id="linearGradient4213"
x1="28.660715"
y1="6.0267878"
x2="10.758928"
y2="10.982145"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4183"
id="linearGradient4221"
x1="18.392859"
y1="30.714291"
x2="23.035715"
y2="12.991074"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.2"
inkscape:cx="53.37166"
inkscape:cy="7.2519486"
inkscape:document-units="px"
inkscape:current-layer="texts"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1832"
inkscape:window-height="966"
inkscape:window-x="0"
inkscape:window-y="30"
inkscape:window-maximized="1" />
<metadata
id="metadata6048">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="black_circle"
transform="translate(8.2538928e-6,2.2345076)"
style="display:inline">
<circle
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.29999995;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4140"
cx="16.250002"
cy="13.122637"
r="15.357144" />
</g>
<g
inkscape:label="symbol"
inkscape:groupmode="layer"
id="layer1"
transform="translate(709.10597,-869.59315)"
style="display:inline">
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;color-interpolation:sRGB;color-interpolation-filters:linearRGB;fill:url(#linearGradient4213);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:60.50111771;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 24.779297,2.2382812 A 5.0549051,5.0549051 0 0 0 23.277344,2.40625 5.0549051,5.0549051 0 0 0 19.552734,6.8925781 l -9.482422,2.5410157 c 0.59171,0.9617502 0.910617,2.0899062 0.878907,3.2539062 l 9.474609,-2.539062 a 5.0549051,5.0549051 0 0 0 5.470703,2.023437 5.0549051,5.0549051 0 0 0 3.574219,-6.1914062 5.0549051,5.0549051 0 0 0 -4.689453,-3.7421876 z"
transform="translate(-709.10597,869.59315)"
id="path4148"
inkscape:connector-curvature="0" />
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;color-interpolation:sRGB;color-interpolation-filters:linearRGB;fill:url(#linearGradient4221);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:60.50111771;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 21.496094,12.3125 -2.539063,9.472656 a 5.0549085,5.0549051 0 0 0 -0.912109,0.152344 5.0549085,5.0549051 0 0 0 -3.576172,6.191406 5.0549085,5.0549051 0 0 0 6.191406,3.574219 5.0549085,5.0549051 0 0 0 3.574219,-6.191406 5.0549085,5.0549051 0 0 0 -2.021484,-2.853516 l 2.539062,-9.480469 C 23.623173,13.209234 22.488304,12.922 21.496094,12.3125 Z"
transform="translate(-709.10597,869.59315)"
id="bottom"
inkscape:connector-curvature="0" />
<g
id="left"
style="fill:#abe3ff;fill-opacity:1">
<g
id="g4156"
style="fill:url(#linearGradient4170);fill-opacity:1">
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;color-interpolation:sRGB;color-interpolation-filters:linearRGB;fill:url(#linearGradient4172);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:60.50111771;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 5.2480469,7.4707031 A 5.0549051,5.0549051 0 0 0 3.7460938,7.640625 5.0549051,5.0549051 0 0 0 0.171875,13.830078 5.0549051,5.0549051 0 0 0 6.3632812,17.40625 5.0549051,5.0549051 0 0 0 7.2304688,17.082031 l 6.9394532,6.9375 c 0.53707,-0.9933 1.354986,-1.832209 2.378906,-2.386719 L 9.6152344,14.699219 A 5.0549051,5.0549051 0 0 0 9.9375,11.214844 5.0549051,5.0549051 0 0 0 5.2480469,7.4707031 Z"
transform="translate(-709.10597,869.59315)"
id="path4146"
inkscape:connector-curvature="0" />
</g>
</g>
<g
id="texts">
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;"
x="-673.66925"
y="887.26001"
id="RETROSHARE"><tspan
sodipodi:role="line"
id="tspan4502"
x="-673.66925"
y="887.26001"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.66666603px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#5eb9e5;fill-opacity:1"
id="tspan4510">RETRO</tspan><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start"
id="tspan4522">SHARE</tspan></tspan></text>
<text
transform="scale(1.0202219,0.98017888)"
id="secure"
y="911.17212"
x="-659.19342"
style="font-style:normal;font-weight:normal;font-size:39.57231903px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.98930794px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.8611412px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.98930794px"
y="911.17212"
x="-659.19342"
id="tspan4506"
sodipodi:role="line">secure communication for everyone</tspan></text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -487,6 +487,20 @@ void NotifyQt::notifyChatLobbyTimeShift(int shift)
emit chatLobbyTimeShift(shift) ; emit chatLobbyTimeShift(shift) ;
} }
void NotifyQt::notifyConnectionWithoutCert()
{
{
QMutexLocker m(&_mutex) ;
if(!_enabled)
return ;
}
#ifdef NOTIFY_DEBUG
std::cerr << "notifyQt: Received notifyConnectionWithoutCert" << std::endl;
#endif
emit connectionWithoutCert();
}
void NotifyQt::handleChatLobbyTimeShift(int /*shift*/) void NotifyQt::handleChatLobbyTimeShift(int /*shift*/)
{ {
return ; // we say nothing. The help dialog of lobbies explains this already. return ; // we say nothing. The help dialog of lobbies explains this already.

View file

@ -52,6 +52,7 @@ class NotifyQt: public QObject, public NotifyClient
virtual void notifyOwnAvatarChanged() ; virtual void notifyOwnAvatarChanged() ;
virtual void notifyChatLobbyEvent(uint64_t /* lobby id */, uint32_t /* event type */, const RsGxsId & /*nickname*/, const std::string& /* any string */) ; virtual void notifyChatLobbyEvent(uint64_t /* lobby id */, uint32_t /* event type */, const RsGxsId & /*nickname*/, const std::string& /* any string */) ;
virtual void notifyChatLobbyTimeShift(int time_shift) ; virtual void notifyChatLobbyTimeShift(int time_shift) ;
void notifyConnectionWithoutCert();
virtual void notifyOwnStatusMessageChanged() ; virtual void notifyOwnStatusMessageChanged() ;
virtual void notifyDiskFull(uint32_t loc,uint32_t size_in_mb) ; virtual void notifyDiskFull(uint32_t loc,uint32_t size_in_mb) ;
@ -143,6 +144,7 @@ class NotifyQt: public QObject, public NotifyClient
void chatLobbyInviteReceived() ; void chatLobbyInviteReceived() ;
void deferredSignatureHandlingRequested() ; void deferredSignatureHandlingRequested() ;
void chatLobbyTimeShift(int time_shift) ; void chatLobbyTimeShift(int time_shift) ;
void connectionWithoutCert();
/* Notify from GUI */ /* Notify from GUI */
void chatFontChanged(); void chatFontChanged();

View file

@ -519,6 +519,21 @@ ServerPage QPlainTextEdit#plainTextEdit {
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2);
} }
ServerPage QPlainTextEdit#hiddenpageInHelpPlainTextEdit {
border: 1px solid #DCDC41;
border-radius: 6px;
background: #FFFFD7;
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2);
}
ServerPage QPlainTextEdit#pteBobSimple {
border: 1px solid #DCDC41;
border-radius: 6px;
background: #FFFFD7;
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2);
}
/* ProfileManager */ /* ProfileManager */
ProfileManager > QFrame#headerFrame { ProfileManager > QFrame#headerFrame {
@ -665,49 +680,49 @@ IdEditDialog QLabel#info_label
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2);
} }
GenCertDialog QComboBox#genPGPuser { GenCertDialog QComboBox#genPGPuser {
border: 4px solid #0099cc; border: 2px solid #0099cc;
border-radius: 6px; border-radius: 6px;
background: white; background: white;
font: bold; font: bold;
} }
GenCertDialog QSpinBox#hiddenport_spinBox { GenCertDialog QSpinBox#hiddenport_spinBox {
border: 4px solid #0099cc; border: 2px solid #0099cc;
border-radius: 6px; border-radius: 6px;
background: white; background: white;
font: bold; font: bold;
} }
GenCertDialog QLineEdit#hiddenaddr_input { GenCertDialog QLineEdit#hiddenaddr_input {
border: 4px solid #0099cc; border: 2px solid #0099cc;
border-radius: 6px; border-radius: 6px;
background: white; background: white;
font: bold; font: bold;
} }
GenCertDialog QLineEdit#password_input_2 { GenCertDialog QLineEdit#password_input_2 {
border: 4px solid #0099cc; border: 2px solid #0099cc;
border-radius: 6px; border-radius: 6px;
background: white; background: white;
font: bold; font: bold;
} }
GenCertDialog QLineEdit#password_input { GenCertDialog QLineEdit#password_input {
border: 4px solid #0099cc; border: 2px solid #0099cc;
border-radius: 6px; border-radius: 6px;
background: white; background: white;
font: bold; font: bold;
} }
GenCertDialog QLineEdit#nickname_input { GenCertDialog QLineEdit#nickname_input {
border: 4px solid #0099cc; border: 2px solid #0099cc;
border-radius: 6px; border-radius: 6px;
background: white; background: white;
font: bold; font: bold;
} }
GenCertDialog QLineEdit#node_input { GenCertDialog QLineEdit#node_input {
border: 4px solid #0099cc; border: 2px solid #0099cc;
border-radius: 6px; border-radius: 6px;
background: white; background: white;
font: bold; font: bold;
} }
GenCertDialog QLineEdit#name_input { GenCertDialog QLineEdit#name_input {
border: 4px solid #0099cc; border: 2px solid #0099cc;
border-radius: 6px; border-radius: 6px;
background: white; background: white;
font: bold; font: bold;
@ -772,4 +787,14 @@ StartDialog QPushButton#loadButton {
StartDialog QPushButton#loadButton:hover { StartDialog QPushButton#loadButton:hover {
border-image: url(:/images/btn_blue_hover.png) 4; border-image: url(:/images/btn_blue_hover.png) 4;
} }
StartDialog QFrame#loginframe{
border-image: url(:/images/logo/background_lessblue.png) 0 0 0 0 stretch stretch;
border-width: 0px;
}
GenCertDialog QFrame#profileframe{
background-image: url(:/images/logo/background.png);
background-repeat: repeat;
}

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