diff --git a/.travis.yml b/.travis.yml index abc796ecd..90a8f8514 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,7 +52,8 @@ addons: branch_pattern: coverity_scan before_script: - - qmake QMAKE_CC=$CC QMAKE_CXX=$CXX CONFIG+=no_sqlcipher CONFIG+=tests + - if [ $TRAVIS_OS_NAME == linux ]; then qmake QMAKE_CC=$CC QMAKE_CXX=$CXX CONFIG+=no_sqlcipher CONFIG+=tests ; fi + - if [ $TRAVIS_OS_NAME == osx ]; then qmake QMAKE_CC=$CC QMAKE_CXX=$CXX CONFIG+=no_sqlcipher CONFIG+=tests CONFIG+=rs_macos10.12 ; fi script: - if [ $TRAVIS_OS_NAME == linux ] && [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then make && tests/unittests/unittests >/dev/null 2>&1 ; fi diff --git a/README-Android.asciidoc b/README-Android.asciidoc index 7c781dda9..433230e9f 100644 --- a/README-Android.asciidoc +++ b/README-Android.asciidoc @@ -106,6 +106,50 @@ To enable enable _protection_: +Android menu -> Settings -> Privacy & security Other devices may offer similar _features_ please report them. +== Debugging with GDB + +QtCreator actually support debugging only for the foreground activity, so to +debug what's happening in the core extra trickery is needed. +First of all you need to authorize root access to applications, then once you +plug your sacrifical Android phone run this commands + +.Run gdbserver as root on Android phone +[source,bash] +-------------------------------------------------------------------------------- +## Open a shell from your workstation on the connected Android phone +adb shell + +## take note of the PID of the RetroShare process +ps | grep retroshare + +## take the note of the phone IP +ip address show + +## Gain root permissions on the shell +su + +## Attach with gdbserver and listen on one TCP port +gdbserver :4567 --attach $RETROSHARE_PID +-------------------------------------------------------------------------------- + + +.Prepare and run Android NDK GDB on your workstation +[source,bash] +-------------------------------------------------------------------------------- +## Extract system lib from the phone to a temporary directory on your computer +adb pull /system/lib /tmp/system_lib + +## Start Android NDK GDB of your phone architecture passing the executable +/opt/android-ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gdb RetroShare-Android_for_armeabi_v7a_GCC_4_9_Qt_5_9_2_android_armv7-Debug/retroshare-android-service/src/libretroshare-android-service.so + +## Instruct GDB how and where to find libraries +(gdb) set auto-solib-add on +(gdb) set solib-search-path /tmp/system_lib + +## Connect to the gdbserver running on the phone +(gdb) target remote $PHONE_IP:4567 +-------------------------------------------------------------------------------- + == Furter Readings @@ -115,3 +159,5 @@ Other devices may offer similar _features_ please report them. - link:retroshare://file?name=Android%20Native%20Development%20Kit%20Cookbook.pdf&size=29214468&hash=0123361c1b14366ce36118e82b90faf7c7b1b136[] - link:https://groups.google.com/forum/#!topic/android-developers/srATPaL0aRU[] - link:https://stackoverflow.com/questions/31638986/protected-apps-setting-on-huawei-phones-and-how-to-handle-it[] +- link:https://tthtlc.wordpress.com/2012/09/19/how-to-do-remote-debugging-via-gdbserver-running-inside-the-android-phone/[] +- link:https://source.android.com/devices/tech/debug/gdb[] diff --git a/build_scripts/Debian+Ubuntu/changelog b/build_scripts/Debian+Ubuntu/changelog index 3062d588c..1d20e719e 100644 --- a/build_scripts/Debian+Ubuntu/changelog +++ b/build_scripts/Debian+Ubuntu/changelog @@ -1,5 +1,78 @@ retroshare (0.6.3-1.XXXXXX~YYYYYY) YYYYYY; urgency=low + c2d5579 csoler Thu, 21 Dec 2017 17:06:32 +0100 storage of chat room icons in local variables to avoid re-reading them from qrc everytime (patch from sss) + acd8355 Gioacc Wed, 20 Dec 2017 18:24:28 +0100 Add some documentation on how to debug retroshare on android + c0d8333 csoler Mon, 18 Dec 2017 16:10:52 +0100 Merge pull request #1136 from csoler/v0.6-FT + ed0e280 csoler Mon, 18 Dec 2017 16:01:27 +0100 Merge pull request #1135 from PhenomRetroShare/Fix_DontSetMacOsTargetIfNotMacOs + 4950ffb Phenom Fri, 15 Dec 2017 10:01:30 +0100 Don't Set Target and SDK if not MacOS + 0895b3d csoler Sun, 17 Dec 2017 13:55:50 +0100 Merge pull request #1134 from PhenomRetroShare/Fix_TravisCI_MacOS_Compil + 3007fec csoler Sat, 16 Dec 2017 17:46:44 +0100 fixed colors in keyring with new ModelIndex based view (patch from sss) + 99e35b1 csoler Sat, 16 Dec 2017 15:04:16 +0100 rename file in partials into real name before moving it; check for destination directory before moving file + a3acd58 Phenom Fri, 8 Dec 2017 19:00:34 +0100 Fix TravisCI on MacOS compilation. + acbcba8 csoler Thu, 7 Dec 2017 17:20:27 +0100 attempt to fix icon sizes in identity dialog + d2c8ba1 csoler Mon, 4 Dec 2017 16:33:45 +0100 Merge pull request #1117 from chelovechishko/qdarkstyle_fix + 22292fc csoler Mon, 4 Dec 2017 16:32:37 +0100 Merge pull request #1118 from RetroPooh/net_settings_antifreeze + 621ed71 csoler Mon, 4 Dec 2017 16:31:48 +0100 Merge pull request #1120 from sehraf/pr_fixForumDownloadAll + 0503f42 csoler Mon, 4 Dec 2017 16:30:29 +0100 Merge pull request #1119 from RetroPooh/chan-fix-cyr + 49b4057 sehraf Sat, 2 Dec 2017 15:00:24 +0100 fix 'download all' button for forum. Now all file links are opened in one collection dialog instead of each link in one separate dialog. + 98d2772 chelov Sat, 2 Dec 2017 17:10:15 +0900 gui: make forums_dialog slightly more readable sometimes + 8ec69df RetroP Wed, 29 Nov 2017 19:23:52 +0300 fix cyrillic text sent wrong in channel post + a88c2ef RetroP Wed, 29 Nov 2017 17:17:49 +0300 fix freezes in network settings + b99a1a5 defnax Tue, 28 Nov 2017 19:36:39 +0100 fixed the emote file for unshown emotes on gui + d1cdba8 Chelov Mon, 27 Nov 2017 14:48:14 +0900 gui: fix probably mistake with names in qdarkstyle.qss + 8c34a50 Chelov Mon, 27 Nov 2017 11:16:37 +0900 gui: fix default color of some text in friends list in qdarkstyle.qss + d566a2a Chelov Mon, 27 Nov 2017 10:54:19 +0900 gui: fix keyring background color in qdarkstyle.qss + c05dd30 Chelov Mon, 27 Nov 2017 10:40:24 +0900 gui: fix doubled semicolons in qdarkstyle.qss + 63b3acb csoler Thu, 23 Nov 2017 21:27:03 +0100 Merge pull request #1113 from csoler/v0.6-SSL110Fix + 1faa274 csoler Wed, 22 Nov 2017 23:46:57 +0100 simplified memory management in certificate signature verification code + 669f2ba csoler Wed, 22 Nov 2017 22:56:40 +0100 fixed a few bugs in signature verification code accross versions + c8c90ab csoler Wed, 22 Nov 2017 20:31:49 +0100 Merge pull request #1115 from PhenomRetroShare/Add_CopyComment + f6d69e0 csoler Wed, 22 Nov 2017 00:02:11 +0100 ensured maximum backward compatibility for crypto changes that will occur in future v0.7 + 6d4c942 Gioacc Tue, 21 Nov 2017 13:28:24 +0100 Removed unnecessary executable flag on some files + 49d2366 csoler Tue, 21 Nov 2017 09:29:52 +0100 fixed windows compilation + ea241f6 csoler Tue, 21 Nov 2017 09:27:21 +0100 restored plugins removed by previous commit + d905144 csoler Mon, 20 Nov 2017 23:18:53 +0100 Merge pull request #1114 from PhenomRetroShare/Fix_DisableReplyToSystemMessage + d1d66bb csoler Mon, 20 Nov 2017 23:17:16 +0100 Merge pull request #1079 from csoler/v0.6-Keyring + e2c1661 csoler Mon, 20 Nov 2017 22:44:34 +0100 fixed compilation with v0.7 defines + cd51afb csoler Mon, 20 Nov 2017 22:26:14 +0100 fixed small bug in signature and compilation + 9367aa0 csoler Sun, 19 Nov 2017 20:15:36 +0100 changed #ifs into #ifdefs because it us more robust, and moved the definition of variables to retroshare.pri + ef1a613 csoler Sun, 19 Nov 2017 19:57:38 +0100 added proper debug output for signature verification + 863e625 csoler Sun, 19 Nov 2017 19:34:54 +0100 centralized the defines into a single file + e72bd9f csoler Sun, 19 Nov 2017 18:38:46 +0100 fixed bug causing certificate rejection + b4fdd4e csoler Sun, 19 Nov 2017 18:21:56 +0100 added two additional non packward compatible changes for future version 0.7, and improvements of verifications of certificate signatures + 46a6bdc Phenom Sat, 18 Nov 2017 19:48:38 +0100 Add Copy action for Gxs Comments. + 71efb9f Phenom Sat, 18 Nov 2017 18:49:42 +0100 Disable ReplyTo if System Message. + 7472f78 csoler Wed, 15 Nov 2017 23:24:43 +0100 added sha256 calculation functions, and non backward compatible SSL Id computation code to active later (0.7) + ce14219 csoler Tue, 14 Nov 2017 21:39:46 +0100 merged with upstream/master + 9f8f0e9 csoler Tue, 14 Nov 2017 21:36:04 +0100 fixed column names in keyring + ba7cf49 csoler Tue, 14 Nov 2017 20:53:24 +0100 Merge pull request #1037 from RetroPooh/searchspy + 556f93c csoler Tue, 14 Nov 2017 20:51:25 +0100 Merge pull request #1108 from RetroPooh/smallfixes2 + 2f6517a csoler Tue, 14 Nov 2017 20:50:57 +0100 Merge pull request #1112 from RetroPooh/coll_name_as_dir + fdced92 csoler Tue, 14 Nov 2017 20:41:48 +0100 Merge pull request #1111 from RetroPooh/searstr + 1f207ba RetroP Tue, 14 Nov 2017 19:52:48 +0300 create collection dialog filename as dir name + 919d650 RetroP Tue, 14 Nov 2017 16:09:05 +0300 in search strings change comma to space for better look + 9aa6dd3 Pooh Tue, 14 Nov 2017 14:34:22 +0300 Update rsturtleitem.h + 8368a76 csoler Mon, 13 Nov 2017 23:38:25 +0100 Merge pull request #1110 from csoler/v0.6-FT + 5fab053 csoler Mon, 13 Nov 2017 23:37:53 +0100 added toStdString() method to search strings so as to display what is searched + 7304c48 csoler Mon, 13 Nov 2017 22:32:30 +0100 Merge pull request #1109 from csoler/v0.6-Links2 + 5d6225a RetroP Tue, 14 Nov 2017 00:14:16 +0300 sort by time, nicer look + 1669cd4 csoler Mon, 13 Nov 2017 22:08:05 +0100 use "download..." menu with RsCollectionDialog with multiple files and directories + f369ac1 RetroP Mon, 13 Nov 2017 19:05:16 +0300 fix mail fields stretching with CC BCC + 45c8e9e csoler Mon, 13 Nov 2017 11:01:48 +0100 Merge pull request #1107 from csoler/v0.6-Links2 + 5997c10 csoler Sun, 12 Nov 2017 22:46:29 +0100 fixed bug causing RsCollection to fail on remote files. Now using RsCollectionDialog when downloading directories from friend shared files + c0951b3 csoler Sun, 12 Nov 2017 21:33:21 +0100 Merge pull request #1040 from RetroPooh/searchmultinames2 + 240d3a6 csoler Sat, 11 Nov 2017 16:33:30 +0100 Merge pull request #1104 from RetroPooh/linkaddrtooltips + cb77243 csoler Sat, 11 Nov 2017 16:31:33 +0100 Merge pull request #1105 from RetroPooh/smallfixes1 + 9b66e7e RetroP Fri, 10 Nov 2017 18:32:18 +0300 fix non-latin peer name display in bw stats + 792f7ff RetroP Fri, 10 Nov 2017 18:31:41 +0300 fix status led icons for distant chat + df244fd RetroP Fri, 10 Nov 2017 16:01:11 +0300 add tooltips with address to urls + 7feb630 csoler Wed, 8 Nov 2017 20:11:26 +0100 Merge pull request #1102 from csoler/v0.6-Links2 + 6a8bc8b csoler Wed, 8 Nov 2017 18:11:46 +0100 use of RsCollectionDialog for processing single file links. Only "extra" links still require the older processing system because RsCollections cannot have sources for each entry + + -- Retroshare Dev Team Thu, 24 Dec 2017 10:00:00 +0100 + +retroshare (0.6.3-1.20171107.c67143d4~wily) wily; urgency=low + 68b35f3 Phenom Tue, 15 Aug 2017 19:45:26 +0200 Fix CppCheck in notifytxt.cc 0b8d684 Phenom Tue, 15 Aug 2017 19:11:32 +0200 Fix CppCheck in framecatcher.cpp deb6693 Phenom Tue, 15 Aug 2017 19:00:17 +0200 Fix CppCheck in idle.cpp diff --git a/libretroshare/src/chat/distributedchat.cc b/libretroshare/src/chat/distributedchat.cc index 19bca229e..ee176c56b 100644 --- a/libretroshare/src/chat/distributedchat.cc +++ b/libretroshare/src/chat/distributedchat.cc @@ -1403,13 +1403,33 @@ bool DistributedChatService::acceptLobbyInvite(const ChatLobbyId& lobby_id,const return false; } + std::map::const_iterator vid = _visible_lobbies.find(lobby_id) ; + + if(_visible_lobbies.end() == vid) + { + std::cerr << " (EE) Cannot subscribe a non visible chat lobby!!" << std::endl; + return false ; + } + + RsIdentityDetails det ; + if( (!rsIdentity->getIdDetails(identity,det)) || !(det.mFlags & RS_IDENTITY_FLAGS_IS_OWN_ID)) + { + std::cerr << " (EE) Cannot subscribe with identity " << identity << " because it is not ours! Something's wrong here." << std::endl; + return false ; + } + + if( (vid->second.lobby_flags & RS_CHAT_LOBBY_FLAGS_PGP_SIGNED ) && !(det.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED)) + { + std::cerr << " (EE) Cannot subscribe with identity " << identity << " because it is unsigned and the lobby requires signed ids only." << std::endl; + return false ; + } + if(_chat_lobbys.find(lobby_id) != _chat_lobbys.end()) { std::cerr << " (II) Lobby already exists. Weird." << std::endl; return true ; } - #ifdef DEBUG_CHAT_LOBBIES std::cerr << " Creating new Lobby entry." << std::endl; #endif @@ -1491,11 +1511,12 @@ void DistributedChatService::denyLobbyInvite(const ChatLobbyId& lobby_id) bool DistributedChatService::joinVisibleChatLobby(const ChatLobbyId& lobby_id,const RsGxsId& gxs_id) { - if(!mGixs->isOwnId(gxs_id)) - { - std::cerr << "(EE) Cannot lobby using gxs id " << gxs_id << std::endl; - return false ; - } + RsIdentityDetails det ; + if( (!rsIdentity->getIdDetails(gxs_id,det)) || !(det.mFlags & RS_IDENTITY_FLAGS_IS_OWN_ID)) + { + std::cerr << " (EE) Cannot subscribe with identity " << gxs_id << " because it is not ours! Something's wrong here." << std::endl; + return false ; + } #ifdef DEBUG_CHAT_LOBBIES std::cerr << "Joining public chat lobby " << std::hex << lobby_id << std::dec << std::endl; @@ -1527,6 +1548,12 @@ bool DistributedChatService::joinVisibleChatLobby(const ChatLobbyId& lobby_id,co return true ; } + if( (it->second.lobby_flags & RS_CHAT_LOBBY_FLAGS_PGP_SIGNED ) && !(det.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED)) + { + std::cerr << " (EE) Cannot subscribe with identity " << gxs_id << " because it is unsigned and the lobby requires signed ids only." << std::endl; + return false ; + } + #ifdef DEBUG_CHAT_LOBBIES std::cerr << " Creating new lobby entry." << std::endl; #endif diff --git a/libretroshare/src/ft/ftcontroller.cc b/libretroshare/src/ft/ftcontroller.cc index d650d1892..382d13cb6 100644 --- a/libretroshare/src/ft/ftcontroller.cc +++ b/libretroshare/src/ft/ftcontroller.cc @@ -734,13 +734,39 @@ bool ftController::completeFile(const RsFileHash& hash) fc->mState = ftFileControl::COMPLETED; + std::string dst_dir,src_dir,src_file,dst_file ; + + RsDirUtil::splitDirFromFile(fc->mCurrentPath,src_dir,src_file) ; + RsDirUtil::splitDirFromFile(fc->mDestination,dst_dir,dst_file) ; + + // We use this intermediate file in case the destination directory is not available, so as to not keep the partial file name. + + std::string intermediate_file_name = src_dir+'/'+dst_file ; + // I don't know how the size can be zero, but believe me, this happens, // and it causes an error on linux because then the file may not even exist. // - if( fc->mSize > 0 && RsDirUtil::moveFile(fc->mCurrentPath,fc->mDestination) ) - fc->mCurrentPath = fc->mDestination; - else + if( fc->mSize == 0) fc->mState = ftFileControl::ERROR_COMPLETION; + else + { + std::cerr << "CompleteFile(): renaming " << fc->mCurrentPath << " into " << fc->mDestination << std::endl; + std::cerr << "CompleteFile(): 1 - renaming " << fc->mCurrentPath << " info " << intermediate_file_name << std::endl; + + if(RsDirUtil::moveFile(fc->mCurrentPath,intermediate_file_name) ) + { + fc->mCurrentPath = intermediate_file_name ; + + std::cerr << "CompleteFile(): 2 - renaming/copying " << intermediate_file_name << " into " << fc->mDestination << std::endl; + + if(RsDirUtil::moveFile(intermediate_file_name,fc->mDestination) ) + fc->mCurrentPath = fc->mDestination; + else + fc->mState = ftFileControl::ERROR_COMPLETION; + } + else + fc->mState = ftFileControl::ERROR_COMPLETION; + } /* for extralist additions */ path = fc->mDestination; diff --git a/libretroshare/src/pgp/pgphandler.cc b/libretroshare/src/pgp/pgphandler.cc index cb6d4e999..df95fc7f9 100644 --- a/libretroshare/src/pgp/pgphandler.cc +++ b/libretroshare/src/pgp/pgphandler.cc @@ -1382,7 +1382,11 @@ ops_secret_key_t *secret_key = NULL ; // then do the signature. ops_boolean_t not_raw = !use_raw_signature ; - ops_memory_t *memres = ops_sign_buf(data,len,(ops_sig_type_t)0x00,secret_key,ops_false,ops_false,not_raw,not_raw) ; +#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_002 + ops_memory_t *memres = ops_sign_buf(data,len,OPS_SIG_BINARY,OPS_HASH_SHA256,secret_key,ops_false,ops_false,not_raw,not_raw) ; +#else + ops_memory_t *memres = ops_sign_buf(data,len,OPS_SIG_BINARY,OPS_HASH_SHA1,secret_key,ops_false,ops_false,not_raw,not_raw) ; +#endif if(!memres) return false ; @@ -1695,16 +1699,16 @@ bool PGPHandler::mergeKeySignatures(ops_keydata_t *dst,const ops_keydata_t *src) bool PGPHandler::parseSignature(unsigned char *sign, unsigned int signlen,RsPgpId& issuer_id) { - uint64_t issuer ; + PGPSignatureInfo info ; - if(!PGPKeyManagement::parseSignature(sign,signlen,issuer)) + if(!PGPKeyManagement::parseSignature(sign,signlen,info)) return false ; unsigned char bytes[8] ; for(int i=0;i<8;++i) { - bytes[7-i] = issuer & 0xff ; - issuer >>= 8 ; + bytes[7-i] = info.issuer & 0xff ; + info.issuer >>= 8 ; } issuer_id = RsPgpId(bytes) ; diff --git a/libretroshare/src/pgp/pgpkeyutil.cc b/libretroshare/src/pgp/pgpkeyutil.cc index c324ab37c..ebd2ccf5b 100644 --- a/libretroshare/src/pgp/pgpkeyutil.cc +++ b/libretroshare/src/pgp/pgpkeyutil.cc @@ -160,7 +160,7 @@ uint32_t PGPKeyManagement::compute24bitsCRC(unsigned char *octets, size_t len) return crc & 0xFFFFFFL; } -bool PGPKeyManagement::parseSignature(const unsigned char *signature, size_t sign_len, uint64_t& issuer) +bool PGPKeyManagement::parseSignature(const unsigned char *signature, size_t sign_len, PGPSignatureInfo& info) { unsigned char *data = (unsigned char *)signature ; @@ -189,10 +189,10 @@ bool PGPKeyManagement::parseSignature(const unsigned char *signature, size_t sig if(signature_type != 4) return false ; - data += 1 ; // skip version number - data += 1 ; // skip signature type - data += 1 ; // skip public key algorithm - data += 1 ; // skip hash algorithm + info.signature_version = data[0] ; data += 1 ; // skip version number + info.signature_type = data[0] ; data += 1 ; // skip signature type + info.public_key_algorithm = data[0] ; data += 1 ; // skip public key algorithm + info.hash_algorithm = data[0] ; data += 1 ; // skip hash algorithm uint32_t hashed_size = 256u*data[0] + data[1] ; data += 2 ; @@ -214,7 +214,7 @@ bool PGPKeyManagement::parseSignature(const unsigned char *signature, size_t sig if(subpacket_type == PGPKeyParser::PGP_PACKET_TAG_ISSUER && subpacket_size == 9) { issuer_found = true ; - issuer = PGPKeyParser::read_KeyID(data) ; + info.issuer = PGPKeyParser::read_KeyID(data) ; } else data += subpacket_size-1 ; // we remove the size of subpacket type diff --git a/libretroshare/src/pgp/pgpkeyutil.h b/libretroshare/src/pgp/pgpkeyutil.h index 9041485f8..672550b1b 100644 --- a/libretroshare/src/pgp/pgpkeyutil.h +++ b/libretroshare/src/pgp/pgpkeyutil.h @@ -41,6 +41,46 @@ #include #include +static const uint8_t PGP_PACKET_TAG_HASH_ALGORITHM_UNKNOWN = 0 ; +static const uint8_t PGP_PACKET_TAG_HASH_ALGORITHM_MD5 = 1 ; +static const uint8_t PGP_PACKET_TAG_HASH_ALGORITHM_SHA1 = 2 ; +static const uint8_t PGP_PACKET_TAG_HASH_ALGORITHM_SHA256 = 8 ; +static const uint8_t PGP_PACKET_TAG_HASH_ALGORITHM_SHA512 = 10 ; + +static const uint8_t PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_UNKNOWN = 0 ; +static const uint8_t PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_RSA_ES = 1 ; +static const uint8_t PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_RSA_E = 2 ; +static const uint8_t PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_RSA_S = 3 ; +static const uint8_t PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_DSA = 17 ; + +static const uint8_t PGP_PACKET_TAG_SIGNATURE_VERSION_UNKNOWN = 0 ; +static const uint8_t PGP_PACKET_TAG_SIGNATURE_VERSION_V3 = 3 ; +static const uint8_t PGP_PACKET_TAG_SIGNATURE_VERSION_V4 = 4 ; + +static const uint8_t PGP_PACKET_TAG_SIGNATURE_TYPE_UNKNOWN = 0xff ; +static const uint8_t PGP_PACKET_TAG_SIGNATURE_TYPE_BINARY_DOCUMENT = 0x00 ; +static const uint8_t PGP_PACKET_TAG_SIGNATURE_TYPE_CANONICAL_TEXT = 0x01 ; +static const uint8_t PGP_PACKET_TAG_SIGNATURE_TYPE_STANDALONE_SIG = 0x02 ; +// All other consts for signature types not used, so not defines. + +class PGPSignatureInfo +{ +public: + PGPSignatureInfo() : + signature_version (PGP_PACKET_TAG_SIGNATURE_VERSION_UNKNOWN), + signature_type (PGP_PACKET_TAG_SIGNATURE_TYPE_UNKNOWN), + issuer (0), + public_key_algorithm(PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_UNKNOWN), + hash_algorithm (PGP_PACKET_TAG_HASH_ALGORITHM_UNKNOWN) + {} + + uint8_t signature_version ; + uint8_t signature_type ; + uint64_t issuer ; + uint8_t public_key_algorithm ; + uint8_t hash_algorithm ; +}; + // This class handles GPG keys. For now we only clean them from signatures, but // in the future, we might cache them to avoid unnecessary calls to gpgme. // @@ -66,7 +106,7 @@ class PGPKeyManagement // static uint32_t compute24bitsCRC(unsigned char *data,size_t len) ; - static bool parseSignature(const unsigned char *signature, size_t sign_len, uint64_t &issuer) ; + static bool parseSignature(const unsigned char *signature, size_t sign_len, PGPSignatureInfo& info) ; }; // This class handles the parsing of PGP packet headers under various (old and new) formats. @@ -74,6 +114,8 @@ class PGPKeyManagement class PGPKeyParser { public: + // These constants correspond to packet tags from RFC4880 + static const uint8_t PGP_PACKET_TAG_PUBLIC_KEY = 6 ; static const uint8_t PGP_PACKET_TAG_USER_ID = 13 ; static const uint8_t PGP_PACKET_TAG_SIGNATURE = 2 ; diff --git a/libretroshare/src/pqi/authssl.cc b/libretroshare/src/pqi/authssl.cc index 4d57b1f24..9956459d3 100644 --- a/libretroshare/src/pqi/authssl.cc +++ b/libretroshare/src/pqi/authssl.cc @@ -40,9 +40,10 @@ #include "rsitems/rsconfigitems.h" #include "util/rsdir.h" #include "util/rsstring.h" +#include "pgp/pgpkeyutil.h" #include "retroshare/rspeers.h" // for RsPeerDetails structure -#include "retroshare/rsids.h" // for RsPeerDetails structure +#include "retroshare/rsids.h" // for RsPeerDetails structure #include "rsserver/p3face.h" /******************** notify of new Cert **************************/ @@ -54,13 +55,17 @@ /* SSL connection diagnostic */ -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_UNKNOWN = 0x00 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_OK = 0x01 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_CERTIFICATE_NOT_VALID = 0x02 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_ISSUER_UNKNOWN = 0x03 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_MALLOC_ERROR = 0x04 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE = 0x05 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_CERTIFICATE_MISSING = 0x06 ; +const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_UNKNOWN = 0x00 ; +const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_OK = 0x01 ; +const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_CERTIFICATE_NOT_VALID = 0x02 ; +const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_ISSUER_UNKNOWN = 0x03 ; +const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_MALLOC_ERROR = 0x04 ; +const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE = 0x05 ; +const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_CERTIFICATE_MISSING = 0x06 ; +const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_HASH_ALGORITHM_NOT_ACCEPTED = 0x07 ; +const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_KEY_ALGORITHM_NOT_ACCEPTED = 0x08 ; +const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE_TYPE = 0x09 ; +const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE_VERSION = 0x0a ; /**** * #define AUTHSSL_DEBUG 1 @@ -528,6 +533,7 @@ bool AuthSSLimpl::validateOwnCertificate(X509 *x509, EVP_PKEY *pkey) /* standard authentication */ if (!AuthX509WithGPG(x509,diagnostic)) { + std::cerr << "Validate Own certificate ERROR: diagnostic = " << diagnostic << std::endl; return false; } return true; @@ -702,7 +708,6 @@ X509 *AuthSSLimpl::SignX509ReqWithGPG(X509_REQ *req, long /*days*/) #define SERIAL_RAND_BITS 64 //const EVP_MD *digest = EVP_sha1(); - ASN1_INTEGER *serial = ASN1_INTEGER_new(); EVP_PKEY *tmppkey; X509 *x509 = X509_new(); if (x509 == NULL) @@ -727,12 +732,28 @@ X509 *AuthSSLimpl::SignX509ReqWithGPG(X509_REQ *req, long /*days*/) std::cerr << "AuthSSLimpl::SignX509Req() Issuer name: " << AuthGPG::getAuthGPG()->getGPGOwnId().toStdString() << std::endl; +#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_002 + static const uint64_t CERTIFICATE_SERIAL_NUMBER = RS_CERTIFICATE_VERSION_NUMBER_07_0001 ; +#else +#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_001 + static const uint64_t CERTIFICATE_SERIAL_NUMBER = RS_CERTIFICATE_VERSION_NUMBER_06_0001 ; +#else + static const uint64_t CERTIFICATE_SERIAL_NUMBER = RS_CERTIFICATE_VERSION_NUMBER_06_0000 ; +#endif +#endif + BIGNUM *btmp = BN_new(); + BN_set_word(btmp,CERTIFICATE_SERIAL_NUMBER) ; + +#ifdef OLD_CODE if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0)) { std::cerr << "AuthSSLimpl::SignX509Req() rand FAIL" << std::endl; return NULL; } +#endif + ASN1_INTEGER *serial = ASN1_INTEGER_new(); + if (!BN_to_ASN1_INTEGER(btmp, serial)) { std::cerr << "AuthSSLimpl::SignX509Req() asn1 FAIL" << std::endl; @@ -763,21 +784,6 @@ X509 *AuthSSLimpl::SignX509ReqWithGPG(X509_REQ *req, long /*days*/) ASN1_TIME_set(X509_get_notBefore(x509), 0); ASN1_TIME_set(X509_get_notAfter(x509), 0); - // OLD code, sets validity time of cert to be between now and some days in the future - /* - if (!X509_gmtime_adj(X509_get_notBefore(x509),0)) - { - std::cerr << "AuthSSLimpl::SignX509Req() notbefore FAIL" << std::endl; - return NULL; - } - - if (!X509_gmtime_adj(X509_get_notAfter(x509), (long)60*60*24*days)) - { - std::cerr << "AuthSSLimpl::SignX509Req() notafter FAIL" << std::endl; - return NULL; - } - */ - if (!X509_set_subject_name(x509, X509_REQ_get_subject_name(req))) { std::cerr << "AuthSSLimpl::SignX509Req() sub FAIL" << std::endl; @@ -815,11 +821,14 @@ X509 *AuthSSLimpl::SignX509ReqWithGPG(X509_REQ *req, long /*days*/) ASN1_BIT_STRING *signature = const_cast(tmp_signature); #endif //EVP_PKEY *pkey = NULL; +#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_002 + const EVP_MD *type = EVP_sha256(); +#else const EVP_MD *type = EVP_sha1(); +#endif EVP_MD_CTX *ctx = EVP_MD_CTX_create(); - int inl=0,hashoutl=0; - int sigoutl=0; + int inl=0; X509_ALGOR *a; /* FIX ALGORITHMS */ @@ -851,48 +860,66 @@ X509 *AuthSSLimpl::SignX509ReqWithGPG(X509_REQ *req, long /*days*/) std::cerr << "Algorithms Fixed" << std::endl; + unsigned int sigoutl=2048; // hashoutl; //EVP_PKEY_size(pkey); + unsigned char *buf_sigout=(unsigned char *)OPENSSL_malloc((unsigned int)sigoutl); + /* input buffer */ #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) inl=i2d(data,NULL); unsigned char *buf_in=(unsigned char *)OPENSSL_malloc((unsigned int)inl); - unsigned char *p=NULL; + + if(buf_in == NULL) + { + sigoutl=0; + fprintf(stderr, "AuthSSLimpl::SignX509Req: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_MALLOC_FAILURE)\n"); + return NULL ; + } + unsigned char *p=buf_in; // This because i2d modifies the pointer after writing to it. + i2d(data,&p); #else unsigned char *buf_in=NULL; inl=i2d_re_X509_tbs(x509,&buf_in) ; // this does the i2d over x509->cert_info #endif - hashoutl=EVP_MD_size(type); - unsigned char *buf_hashout=(unsigned char *)OPENSSL_malloc((unsigned int)hashoutl); - - sigoutl=2048; // hashoutl; //EVP_PKEY_size(pkey); - unsigned char *buf_sigout=(unsigned char *)OPENSSL_malloc((unsigned int)sigoutl); - - if ((buf_in == NULL) || (buf_hashout == NULL) || (buf_sigout == NULL)) - { - hashoutl=0; - sigoutl=0; - fprintf(stderr, "AuthSSLimpl::SignX509Req: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_MALLOC_FAILURE)\n"); - goto err; - } +#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_003 + if((buf_in == NULL) || (buf_sigout == NULL)) + { + sigoutl=0; + fprintf(stderr, "AuthSSLimpl::SignX509Req: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_MALLOC_FAILURE)\n"); + goto err; + } std::cerr << "Buffers Allocated" << std::endl; -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - p=buf_in; - i2d(data,&p); -#endif + /* NOW Sign via GPG Functions */ + if (!AuthGPG::getAuthGPG()->SignDataBin(buf_in, inl, buf_sigout, (unsigned int *) &sigoutl,"AuthSSLimpl::SignX509ReqWithGPG()")) + { + sigoutl = 0; + goto err; + } +#else + unsigned int hashoutl=EVP_MD_size(type); + unsigned char *buf_hashout=(unsigned char *)OPENSSL_malloc((unsigned int)hashoutl); + + if((buf_hashout == NULL) || (buf_sigout == NULL)) + { + hashoutl=0; + sigoutl=0; + fprintf(stderr, "AuthSSLimpl::SignX509Req: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_MALLOC_FAILURE)\n"); + goto err; + } + std::cerr << "Buffers Allocated" << std::endl; /* data in buf_in, ready to be hashed */ EVP_DigestInit_ex(ctx,type, NULL); EVP_DigestUpdate(ctx,(unsigned char *)buf_in,inl); - if (!EVP_DigestFinal(ctx,(unsigned char *)buf_hashout, - (unsigned int *)&hashoutl)) - { - hashoutl=0; - fprintf(stderr, "AuthSSLimpl::SignX509Req: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_EVP_LIB)\n"); - goto err; - } + if (!EVP_DigestFinal(ctx,(unsigned char *)buf_hashout, (unsigned int *)&hashoutl)) + { + hashoutl=0; + fprintf(stderr, "AuthSSLimpl::SignX509Req: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_EVP_LIB)\n"); + goto err; + } - std::cerr << "Digest Applied: len: " << hashoutl << std::endl; + std::cerr << "Digest Applied: len: " << hashoutl << std::endl; /* NOW Sign via GPG Functions */ if (!AuthGPG::getAuthGPG()->SignDataBin(buf_hashout, hashoutl, buf_sigout, (unsigned int *) &sigoutl,"AuthSSLimpl::SignX509ReqWithGPG()")) @@ -900,9 +927,12 @@ X509 *AuthSSLimpl::SignX509ReqWithGPG(X509_REQ *req, long /*days*/) sigoutl = 0; goto err; } +#endif std::cerr << "Buffer Sizes: in: " << inl; +#ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_003 std::cerr << " HashOut: " << hashoutl; +#endif std::cerr << " SigOut: " << sigoutl; std::cerr << std::endl; @@ -926,6 +956,13 @@ X509 *AuthSSLimpl::SignX509ReqWithGPG(X509_REQ *req, long /*days*/) EVP_MD_CTX_destroy(ctx) ; + // debug + // { + // int pkey_nid = OBJ_obj2nid(x509->sig_alg->algorithm); + // const char* sslbuf = OBJ_nid2ln(pkey_nid); + // std::cerr << "Signature hash algorithm: " << sslbuf << std::endl; + // } + return x509; /* XXX CLEANUP */ @@ -933,8 +970,10 @@ X509 *AuthSSLimpl::SignX509ReqWithGPG(X509_REQ *req, long /*days*/) /* cleanup */ if(buf_in != NULL) OPENSSL_free(buf_in) ; +#ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_003 if(buf_hashout != NULL) OPENSSL_free(buf_hashout) ; +#endif if(buf_sigout != NULL) OPENSSL_free(buf_sigout) ; std::cerr << "GPGAuthMgr::SignX509Req() err: FAIL" << std::endl; @@ -992,12 +1031,13 @@ bool AuthSSLimpl::AuthX509WithGPG(X509 *x509,uint32_t& diagnostic) X509_get0_signature(&signature,&algor2,x509); #endif - - const EVP_MD *type = EVP_sha1(); + uint32_t certificate_version = getX509RetroshareCertificateVersion(x509) ; EVP_MD_CTX *ctx = EVP_MD_CTX_create(); - int inl=0,hashoutl=0; - int sigoutl=0; + int inl=0; + + const unsigned char *signed_data = NULL ; + uint32_t signed_data_length =0; /* input buffer */ #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) @@ -1009,25 +1049,12 @@ bool AuthSSLimpl::AuthX509WithGPG(X509 *x509,uint32_t& diagnostic) inl=i2d_re_X509_tbs(x509,&buf_in) ; // this does the i2d over x509->cert_info #endif - hashoutl=EVP_MD_size(type); - unsigned char *buf_hashout=(unsigned char *)OPENSSL_malloc((unsigned int)hashoutl); - - sigoutl=2048; //hashoutl; //EVP_PKEY_size(pkey); - unsigned char *buf_sigout=(unsigned char *)OPENSSL_malloc((unsigned int)sigoutl); - -#ifdef AUTHSSL_DEBUG - std::cerr << "Buffer Sizes: in: " << inl; - std::cerr << " HashOut: " << hashoutl; - std::cerr << " SigOut: " << sigoutl; - std::cerr << std::endl; -#endif - - if ((buf_in == NULL) || (buf_hashout == NULL) || (buf_sigout == NULL)) { - hashoutl=0; - sigoutl=0; + if(buf_in == NULL) + { fprintf(stderr, "AuthSSLimpl::AuthX509: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_MALLOC_FAILURE)\n"); diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_MALLOC_ERROR ; - goto err; + + return false ; } #ifdef AUTHSSL_DEBUG @@ -1038,44 +1065,106 @@ bool AuthSSLimpl::AuthX509WithGPG(X509 *x509,uint32_t& diagnostic) p=buf_in; i2d(data,&p); #endif - /* data in buf_in, ready to be hashed */ - EVP_DigestInit_ex(ctx,type, NULL); - EVP_DigestUpdate(ctx,(unsigned char *)buf_in,inl); - if (!EVP_DigestFinal(ctx,(unsigned char *)buf_hashout, - (unsigned int *)&hashoutl)) - { - hashoutl=0; - fprintf(stderr, "AuthSSLimpl::AuthX509: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_EVP_LIB)\n"); - diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_MALLOC_ERROR ; - goto err; - } + { // this scope is to avoid cross-initialization jumps to err. + + const Sha1CheckSum sha1 = RsDirUtil::sha1sum(buf_in,inl) ; // olds the memory until destruction + + if(certificate_version < RS_CERTIFICATE_VERSION_NUMBER_07_0001) + { + // If the certificate belongs to 0.6 version, we hash it here, and then re-hash the hash it in the PGP signature. + + signed_data = sha1.toByteArray() ; + signed_data_length = sha1.SIZE_IN_BYTES; + } + else + { + signed_data = buf_in ; + signed_data_length = inl ; + } + + /* NOW check sign via GPG Functions */ + //get the fingerprint of the key that is supposed to sign #ifdef AUTHSSL_DEBUG - std::cerr << "Digest Applied: len: " << hashoutl << std::endl; + std::cerr << "AuthSSLimpl::AuthX509() verifying the gpg sig with keyprint : " << pd.fpr << std::endl; + std::cerr << "Sigoutl = " << sigoutl << std::endl ; + std::cerr << "pd.fpr = " << pd.fpr << std::endl ; #endif - /* copy data into signature */ - if(sigoutl < signature->length) - { - diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_MALLOC_ERROR ; - goto err; - } - sigoutl = signature->length; - memmove(buf_sigout, signature->data, sigoutl); + // Take a early look at signature parameters. In particular we dont accept signatures with unsecure hash algorithms. - /* NOW check sign via GPG Functions */ - //get the fingerprint of the key that is supposed to sign -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSLimpl::AuthX509() verifying the gpg sig with keyprint : " << pd.fpr << std::endl; - std::cerr << "Sigoutl = " << sigoutl << std::endl ; - std::cerr << "pd.fpr = " << pd.fpr << std::endl ; - std::cerr << "hashoutl = " << hashoutl << std::endl ; -#endif + PGPSignatureInfo signature_info ; + PGPKeyManagement::parseSignature(signature->data,signature->length,signature_info) ; - if (!AuthGPG::getAuthGPG()->VerifySignBin(buf_hashout, hashoutl, buf_sigout, (unsigned int) sigoutl, pd.fpr)) { - sigoutl = 0; - diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE ; - goto err; + if(signature_info.signature_version != PGP_PACKET_TAG_SIGNATURE_VERSION_V4) + { + diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE_VERSION ; + goto err ; + } + + std::string sigtypestring ; + + switch(signature_info.signature_type) + { + case PGP_PACKET_TAG_SIGNATURE_TYPE_BINARY_DOCUMENT : + break ; + + case PGP_PACKET_TAG_SIGNATURE_TYPE_STANDALONE_SIG : + case PGP_PACKET_TAG_SIGNATURE_TYPE_CANONICAL_TEXT : + case PGP_PACKET_TAG_SIGNATURE_TYPE_UNKNOWN : + default: + diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE_TYPE ; + goto err ; + } + + switch(signature_info.public_key_algorithm) + { + case PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_RSA_ES : + case PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_RSA_S : sigtypestring = "RSA" ; + break ; + + case PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_DSA : sigtypestring = "DSA" ; + break ; + + case PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_RSA_E : + case PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_UNKNOWN: + default: + diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_HASH_ALGORITHM_NOT_ACCEPTED ; + goto err ; + } + + switch(signature_info.hash_algorithm) + { + case PGP_PACKET_TAG_HASH_ALGORITHM_SHA1 : sigtypestring += "+SHA1" ; break; + case PGP_PACKET_TAG_HASH_ALGORITHM_SHA256: sigtypestring += "+SHA256" ; break; + case PGP_PACKET_TAG_HASH_ALGORITHM_SHA512: sigtypestring += "+SHA512" ; break; + + // We dont accept signatures with unknown or week hash algorithms. + + case PGP_PACKET_TAG_HASH_ALGORITHM_MD5: + case PGP_PACKET_TAG_HASH_ALGORITHM_UNKNOWN: + default: + diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_HASH_ALGORITHM_NOT_ACCEPTED ; + goto err ; + } + + // passed, verify the signature itself + + if (!AuthGPG::getAuthGPG()->VerifySignBin(signed_data, signed_data_length, signature->data, signature->length, pd.fpr)) + { + diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE ; + goto err; + } + + RsPeerId peerIdstr ; + getX509id(x509, peerIdstr) ; + + std::string fpr = pd.fpr.toStdString(); + std::cerr << "Verified " << sigtypestring << " signature of certificate " << peerIdstr << ", Version " << std::hex << certificate_version + << std::dec << " using PGP key " ; + for(uint32_t i=0;isecond).hiddenType; } +bool p3PeerMgrIMPL::isHiddenNode(const RsPeerId& id) +{ + RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ + + if (id == AuthSSL::getAuthSSL()->OwnId()) + return mOwnState.hiddenNode ; + else + { + std::map::const_iterator it = mFriendList.find(id); + + if (it == mFriendList.end()) + { + std::cerr << "p3PeerMgrIMPL::isHiddenNode() Peer Not Found" << std::endl; + return false; + } + return it->second.hiddenNode ; + } +} + /** * @brief sets hidden domain and port for a given ssl ID * @param ssl_id peer to set domain and port for @@ -1632,6 +1651,8 @@ bool p3PeerMgrIMPL::updateAddressList(const RsPeerId& id, const pqiIpAddrSet cleanIpList(clean_set.mExt.mAddrs,id,mLinkMgr) ; cleanIpList(clean_set.mLocal.mAddrs,id,mLinkMgr) ; + bool am_I_a_hidden_node = isHiddenNode(getOwnId()) ; + RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ /* check if it is our own ip */ @@ -1655,7 +1676,12 @@ bool p3PeerMgrIMPL::updateAddressList(const RsPeerId& id, const pqiIpAddrSet } /* "it" points to peer */ - it->second.ipAddrs.updateAddrs(clean_set); + + if(!am_I_a_hidden_node) + it->second.ipAddrs.updateAddrs(clean_set); + else + it->second.ipAddrs.clear(); + #ifdef PEER_DEBUG std::cerr << "p3PeerMgrIMPL::setLocalAddress() Updated Address for: " << id; std::cerr << std::endl; @@ -2173,6 +2199,7 @@ bool p3PeerMgrIMPL::loadList(std::list& load) #endif RsPeerId ownId = getOwnId(); + bool am_I_a_hidden_node = isHiddenNode(ownId) ; /* load the list of peers */ std::list::iterator it; @@ -2220,16 +2247,20 @@ bool p3PeerMgrIMPL::loadList(std::list& load) } else { - setLocalAddress(peer_id, pitem->localAddrV4.addr); - setExtAddress(peer_id, pitem->extAddrV4.addr); - setDynDNS (peer_id, pitem->dyndns); - - /* convert addresses */ pqiIpAddrSet addrs; - addrs.mLocal.extractFromTlv(pitem->localAddrList); - addrs.mExt.extractFromTlv(pitem->extAddrList); - updateAddressList(peer_id, addrs); + if(!am_I_a_hidden_node) // clear IPs if w're a hidden node. Friend's clear node IPs where previously sent. + { + setLocalAddress(peer_id, pitem->localAddrV4.addr); + setExtAddress(peer_id, pitem->extAddrV4.addr); + setDynDNS (peer_id, pitem->dyndns); + + /* convert addresses */ + addrs.mLocal.extractFromTlv(pitem->localAddrList); + addrs.mExt.extractFromTlv(pitem->extAddrList); + } + + updateAddressList(peer_id, addrs); } delete(*it); diff --git a/libretroshare/src/pqi/p3peermgr.h b/libretroshare/src/pqi/p3peermgr.h index f0a9a44cb..8fa73cf78 100644 --- a/libretroshare/src/pqi/p3peermgr.h +++ b/libretroshare/src/pqi/p3peermgr.h @@ -171,6 +171,7 @@ virtual bool setVisState(const RsPeerId &id, uint16_t vs_disc, uint16_t vs_dht) virtual bool setLocation(const RsPeerId &pid, const std::string &location) = 0; virtual bool setHiddenDomainPort(const RsPeerId &id, const std::string &domain_addr, const uint16_t domain_port) = 0; +virtual bool isHiddenNode(const RsPeerId& id) = 0 ; virtual bool updateCurrentAddress(const RsPeerId& id, const pqiIpAddress &addr) = 0; virtual bool updateLastContact(const RsPeerId& id) = 0; @@ -284,6 +285,7 @@ public: virtual bool setLocation(const RsPeerId &pid, const std::string &location); virtual bool setHiddenDomainPort(const RsPeerId &id, const std::string &domain_addr, const uint16_t domain_port); + virtual bool isHiddenNode(const RsPeerId& id); virtual bool updateCurrentAddress(const RsPeerId& id, const pqiIpAddress &addr); virtual bool updateLastContact(const RsPeerId& id); diff --git a/libretroshare/src/pqi/pqiipset.h b/libretroshare/src/pqi/pqiipset.h index 1ac7da3ea..29c8aaddd 100644 --- a/libretroshare/src/pqi/pqiipset.h +++ b/libretroshare/src/pqi/pqiipset.h @@ -68,6 +68,12 @@ class pqiIpAddrSet void printAddrs(std::string &out) const; pqiIpAddrList mLocal; pqiIpAddrList mExt; + + void clear() + { + mLocal.mAddrs.clear(); + mExt.mAddrs.clear(); + } }; diff --git a/libretroshare/src/pqi/pqisslproxy.cc b/libretroshare/src/pqi/pqisslproxy.cc old mode 100755 new mode 100644 diff --git a/libretroshare/src/pqi/pqisslproxy.h b/libretroshare/src/pqi/pqisslproxy.h old mode 100755 new mode 100644 diff --git a/libretroshare/src/pqi/sslfns.cc b/libretroshare/src/pqi/sslfns.cc index ab79d9825..ff964c45c 100644 --- a/libretroshare/src/pqi/sslfns.cc +++ b/libretroshare/src/pqi/sslfns.cc @@ -610,31 +610,53 @@ bool getX509id(X509 *x509, RsPeerId& xid) X509_get0_signature(&signature,&algor,x509); #endif - int signlen = ASN1_STRING_length(signature); - if (signlen < CERTSIGNLEN) + + uint32_t version_number = getX509RetroshareCertificateVersion(x509) ; + + if(version_number >= RS_CERTIFICATE_VERSION_NUMBER_06_0001) { -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::getX509id() ERROR: Short Signature"; - std::cerr << std::endl; -#endif - return false; + // What: Computes the node id by performing a sha256 hash of the certificate's PGP signature, instead of simply picking up the last 20 bytes of it. + // + // Why: There is no real risk in forging a certificate with the same ID as the authentication is performed over the PGP signature of the certificate + // which hashes the full SSL certificate (i.e. the full serialized CERT_INFO structure). However the possibility to + // create two certificates with the same IDs is a problem, as it can be used to cause disturbance in the software. + // + // Backward compat: makes connexions impossible with non patched peers, probably because the SSL id that is computed is not the same on both side, + // and in particular unpatched peers see a cerficate with ID different (because computed with the old method) than the ID that was + // submitted when making friends. + // + // Note: the advantage of basing the ID on the signature rather than the public key is not very clear, given that the signature is based on a hash + // of the public key (and the rest of the certificate info). + // + + if(RsPeerId::SIZE_IN_BYTES > Sha256CheckSum::SIZE_IN_BYTES) + return false ; + + xid = RsPeerId(RsDirUtil::sha256sum(ASN1_STRING_data(const_cast(signature)),ASN1_STRING_length(signature)).toByteArray()) ; } + else + { + int signlen = ASN1_STRING_length(signature); + if (signlen < CERTSIGNLEN) + { +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSL::getX509id() ERROR: Short Signature"; + std::cerr << std::endl; +#endif + return false; + } - // else copy in the first CERTSIGNLEN. - unsigned char *signdata = ASN1_STRING_data(const_cast(signature)); + // else copy in the first CERTSIGNLEN. + unsigned char *signdata = ASN1_STRING_data(const_cast(signature)); - /* switched to the other end of the signature. for - * more randomness - */ + /* switched to the other end of the signature. for + * more randomness + */ -#warning csoler 2017-02-19: This is cryptographically horrible. We should do a hash of the public key here!!! +#warning csoler 2017-02-19: This is cryptographically horrible. We should hash the entire signature here! - xid = RsPeerId(&signdata[signlen - CERTSIGNLEN]) ; - - //for(int i = signlen - CERTSIGNLEN; i < signlen; i++) - //{ - // rs_sprintf_append(xid, "%02x", (uint16_t) (((uint8_t *) (signdata))[i])); - //} + xid = RsPeerId(&signdata[signlen - CERTSIGNLEN]) ; + } return true; } @@ -663,6 +685,34 @@ bool CheckX509Certificate(X509 */*x509*/) return true; } +uint64_t getX509SerialNumber(X509 *cert) +{ + ASN1_INTEGER *serial = X509_get_serialNumber(cert); + + BIGNUM *btmp = ASN1_INTEGER_to_BN(serial, NULL); + + uint64_t res = BN_get_word(btmp) ; + BN_free(btmp); + + return res ; +} + +uint32_t getX509RetroshareCertificateVersion(X509 *cert) +{ + // Because the serial number was totally random before being used to identity the handshake protocol, we check if we see known version strings. If not, + // we assume v0.6-0000 + // + // We compare the uint32_t into a uint64_t on purpose,to make sure that the highest bits are 0 and not random. + + switch(getX509SerialNumber(cert)) + { + case uint64_t(RS_CERTIFICATE_VERSION_NUMBER_06_0000): return RS_CERTIFICATE_VERSION_NUMBER_06_0000 ; + case uint64_t(RS_CERTIFICATE_VERSION_NUMBER_06_0001): return RS_CERTIFICATE_VERSION_NUMBER_06_0001 ; + case uint64_t(RS_CERTIFICATE_VERSION_NUMBER_07_0001): return RS_CERTIFICATE_VERSION_NUMBER_07_0001 ; + default: + return RS_CERTIFICATE_VERSION_NUMBER_06_0000; + } +} // Not dependent on sslroot. load, and detroys the X509 memory. int LoadCheckX509(const char *cert_file, RsPgpId& issuerName, std::string &location, RsPeerId &userId) diff --git a/libretroshare/src/pqi/sslfns.h b/libretroshare/src/pqi/sslfns.h index 3821c4872..4682810b5 100644 --- a/libretroshare/src/pqi/sslfns.h +++ b/libretroshare/src/pqi/sslfns.h @@ -61,7 +61,15 @@ int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key); #endif +// Certificates serial number is used to store the protocol version for the handshake. (*) means current version. +// +// 06_0000: < Nov.2017. +// * 06_0001: > Nov 2017. SSL id is computed by hashing the entire signature of the cert instead of simply picking up the last bytes. +// 07_0001: Signatures are performed using SHA256+RSA instead of SHA1+RSA +static const uint32_t RS_CERTIFICATE_VERSION_NUMBER_06_0000 = 0x00060000 ; // means version RS-0.6, certificate version 0. Default version before patch. +static const uint32_t RS_CERTIFICATE_VERSION_NUMBER_06_0001 = 0x00060001 ; // means version RS-0.6, certificate version 1. +static const uint32_t RS_CERTIFICATE_VERSION_NUMBER_07_0001 = 0x00070001 ; // means version RS-0.7, certificate version 1. X509_REQ *GenerateX509Req( std::string pkey_file, std::string passwd, @@ -122,6 +130,9 @@ std::string getX509OrgString(X509_NAME *name); std::string getX509CountryString(X509_NAME *name); std::string getX509Info(X509 *cert); +uint64_t getX509SerialNumber(X509 *cert); +uint32_t getX509RetroshareCertificateVersion(X509 *cert) ; + /********** SSL ERROR STUFF ******************************************/ int printSSLError(SSL *ssl, int retval, int err, unsigned long err2, std::string &out); diff --git a/libretroshare/src/retroshare/rsexpr.h b/libretroshare/src/retroshare/rsexpr.h index 4cf9e7983..06aba7e20 100644 --- a/libretroshare/src/retroshare/rsexpr.h +++ b/libretroshare/src/retroshare/rsexpr.h @@ -28,6 +28,7 @@ #include #include #include +#include "util/rsprint.h" #include "retroshare/rstypes.h" /****************************************************************************************** @@ -85,7 +86,9 @@ public: EXPR_SIZE_MB = 8 } token ; static Expression *toExpr(const LinearizedExpression& e) ; - + + std::string GetStrings(); + private: static Expression *toExpr(const LinearizedExpression& e,int&,int&,int&) ; static void readStringExpr(const LinearizedExpression& e,int& n_ints,int& n_strings,std::list& strings,bool& b,StringOperator& op) ; @@ -127,6 +130,7 @@ public: virtual ~Expression() {}; virtual void linearize(LinearizedExpression& e) const = 0 ; + virtual std::string toStdString() const = 0 ; }; class CompoundExpression : public Expression @@ -155,6 +159,18 @@ public: delete Rexp; } + virtual std::string toStdString() const + { + switch(Op) + { + case AndOp: return "(" + Lexp->toStdString() + ") AND (" + Rexp->toStdString() +")" ; + case OrOp: return "(" + Lexp->toStdString() + ") OR (" + Rexp->toStdString() +")" ; + case XorOp: return "(" + Lexp->toStdString() + ") XOR (" + Rexp->toStdString() +")" ; + default: + return "" ; + } + } + virtual void linearize(LinearizedExpression& e) const ; private: Expression *Lexp; @@ -169,6 +185,7 @@ public: StringExpression(enum StringOperator op, std::list &t, bool ic): Op(op),terms(t), IgnoreCase(ic){} virtual void linearize(LinearizedExpression& e) const ; + virtual std::string toStdString(const std::string& varstr) const; protected: bool evalStr(const std::string &str); @@ -184,6 +201,7 @@ public: RelExpression(enum RelOperator op, T lv, T hv): Op(op), LowerValue(lv), HigherValue(hv) {} virtual void linearize(LinearizedExpression& e) const ; + virtual std::string toStdString(const std::string& typestr) const; protected: bool evalRel(T val); @@ -214,6 +232,22 @@ bool RelExpression::evalRel(T val) { } } +template +std::string RelExpression::toStdString(const std::string& typestr) const +{ + std::string LowerValueStr = RsUtil::NumberToString(LowerValue) ; + + switch (Op) { + case Equals: return typestr + " = " + LowerValueStr ; + case GreaterEquals: return typestr + " <= "+ LowerValueStr ; + case Greater: return typestr + " < " + LowerValueStr ; + case SmallerEquals: return typestr + " >= "+ LowerValueStr ; + case Smaller: return typestr + " > " + LowerValueStr ; + case InRange: return LowerValueStr + " <= " + typestr + " <= " + RsUtil::NumberToString(HigherValue) ; + default: + return ""; + } +} /****************************************************************************************** Binary Predicate for Case Insensitive search @@ -245,6 +279,8 @@ public: StringExpression(op,t,ic) {} bool eval(const ExpFileEntry& file); + virtual std::string toStdString() const { return StringExpression::toStdString("NAME"); } + virtual void linearize(LinearizedExpression& e) const { e._tokens.push_back(LinearizedExpression::EXPR_NAME) ; @@ -258,6 +294,8 @@ public: StringExpression(op,t,ic) {} bool eval(const ExpFileEntry& file); + virtual std::string toStdString()const { return StringExpression::toStdString("PATH"); } + virtual void linearize(LinearizedExpression& e) const { e._tokens.push_back(LinearizedExpression::EXPR_PATH) ; @@ -271,6 +309,8 @@ public: StringExpression(op,t,ic) {} bool eval(const ExpFileEntry& file); + virtual std::string toStdString()const { return StringExpression::toStdString("EXTENSION"); } + virtual void linearize(LinearizedExpression& e) const { e._tokens.push_back(LinearizedExpression::EXPR_EXT) ; @@ -284,6 +324,8 @@ public: StringExpression(op,t, true) {} bool eval(const ExpFileEntry& file); + virtual std::string toStdString() const { return StringExpression::toStdString("HASH"); } + virtual void linearize(LinearizedExpression& e) const { e._tokens.push_back(LinearizedExpression::EXPR_HASH) ; @@ -304,6 +346,8 @@ public: RelExpression(op,lv,hv) {} bool eval(const ExpFileEntry& file); + virtual std::string toStdString() const { return RelExpression::toStdString("DATE"); } + virtual void linearize(LinearizedExpression& e) const { e._tokens.push_back(LinearizedExpression::EXPR_DATE) ; @@ -319,6 +363,8 @@ public: RelExpression(op,lv,hv) {} bool eval(const ExpFileEntry& file); + virtual std::string toStdString() const { return RelExpression::toStdString("SIZE"); } + virtual void linearize(LinearizedExpression& e) const { e._tokens.push_back(LinearizedExpression::EXPR_SIZE) ; @@ -334,6 +380,8 @@ public: RelExpression(op,lv,hv) {} bool eval(const ExpFileEntry& file); + virtual std::string toStdString() const { return RelExpression::toStdString("SIZE"); } + virtual void linearize(LinearizedExpression& e) const { e._tokens.push_back(LinearizedExpression::EXPR_SIZE_MB) ; @@ -348,6 +396,8 @@ public: PopExpression(const LinearizedExpression& e) ; bool eval(const ExpFileEntry& file); + virtual std::string toStdString() const { return RelExpression::toStdString("POPULARITY"); } + virtual void linearize(LinearizedExpression& e) const { e._tokens.push_back(LinearizedExpression::EXPR_POP) ; diff --git a/libretroshare/src/retroshare/rsids.h b/libretroshare/src/retroshare/rsids.h index addd08a85..21a8fd754 100644 --- a/libretroshare/src/retroshare/rsids.h +++ b/libretroshare/src/retroshare/rsids.h @@ -221,6 +221,7 @@ static const int CERT_SIGN_LEN = 16 ; // = CERTSIGNLEN static const int PGP_KEY_ID_SIZE = 8 ; static const int PGP_KEY_FINGERPRINT_SIZE = 20 ; static const int SHA1_SIZE = 20 ; +static const int SHA256_SIZE = 32 ; // These constants are random, but should be different, in order to make the various IDs incompatible with each other. // @@ -236,10 +237,12 @@ static const uint32_t RS_GENERIC_ID_GROUTER_ID_TYPE = 0x0009 ; static const uint32_t RS_GENERIC_ID_GXS_TUNNEL_ID_TYPE = 0x0010 ; static const uint32_t RS_GENERIC_ID_GXS_DISTANT_CHAT_ID_TYPE = 0x0011 ; static const uint32_t RS_GENERIC_ID_NODE_GROUP_ID_TYPE = 0x0012 ; +static const uint32_t RS_GENERIC_ID_SHA256_ID_TYPE = 0x0013 ; typedef t_RsGenericIdType< SSL_ID_SIZE , false, RS_GENERIC_ID_SSL_ID_TYPE> SSLIdType ; typedef t_RsGenericIdType< PGP_KEY_ID_SIZE , true, RS_GENERIC_ID_PGP_ID_TYPE> PGPIdType ; typedef t_RsGenericIdType< SHA1_SIZE , false, RS_GENERIC_ID_SHA1_ID_TYPE> Sha1CheckSum ; +typedef t_RsGenericIdType< SHA256_SIZE , false, RS_GENERIC_ID_SHA256_ID_TYPE> Sha256CheckSum ; typedef t_RsGenericIdType< PGP_KEY_FINGERPRINT_SIZE, true, RS_GENERIC_ID_PGP_FINGERPRINT_TYPE> PGPFingerprintType ; typedef t_RsGenericIdType< CERT_SIGN_LEN , false, RS_GENERIC_ID_GXS_GROUP_ID_TYPE > GXSGroupId ; diff --git a/libretroshare/src/retroshare/rspeers.h b/libretroshare/src/retroshare/rspeers.h index c9afe9c1c..f1b274d09 100644 --- a/libretroshare/src/retroshare/rspeers.h +++ b/libretroshare/src/retroshare/rspeers.h @@ -368,6 +368,7 @@ public: virtual bool setHiddenNode(const RsPeerId &id, const std::string &hidden_node_address) = 0; virtual bool setHiddenNode(const RsPeerId &id, const std::string &address, uint16_t port) = 0; + virtual bool isHiddenNode(const RsPeerId &id) = 0; virtual bool setLocalAddress(const RsPeerId &ssl_id, const std::string &addr, uint16_t port) = 0; virtual bool setExtAddress( const RsPeerId &ssl_id, const std::string &addr, uint16_t port) = 0; diff --git a/libretroshare/src/retroshare/rsturtle.h b/libretroshare/src/retroshare/rsturtle.h index 4ad7f2d02..818920487 100644 --- a/libretroshare/src/retroshare/rsturtle.h +++ b/libretroshare/src/retroshare/rsturtle.h @@ -59,6 +59,7 @@ struct TurtleRequestDisplayInfo RsPeerId source_peer_id ; // Peer that relayed the request uint32_t age ; // Age in seconds uint32_t depth ; // Depth of the request. Might be altered. + std::string keywords; }; class TurtleTrafficStatisticsInfo diff --git a/libretroshare/src/rsserver/p3peers.cc b/libretroshare/src/rsserver/p3peers.cc index 113489cd6..9292e1562 100644 --- a/libretroshare/src/rsserver/p3peers.cc +++ b/libretroshare/src/rsserver/p3peers.cc @@ -882,6 +882,11 @@ bool p3Peers::setHiddenNode(const RsPeerId &id, const std::string &hidden_node_ } +bool p3Peers::isHiddenNode(const RsPeerId &id) +{ + return mPeerMgr->isHiddenNode(id) ; +} + bool p3Peers::setHiddenNode(const RsPeerId &id, const std::string &address, uint16_t port) { #ifdef P3PEERS_DEBUG diff --git a/libretroshare/src/rsserver/p3peers.h b/libretroshare/src/rsserver/p3peers.h index 889715aff..4f9b661d7 100644 --- a/libretroshare/src/rsserver/p3peers.h +++ b/libretroshare/src/rsserver/p3peers.h @@ -94,6 +94,7 @@ public: virtual bool setLocation(const RsPeerId &ssl_id, const std::string &location);//location is shown in the gui to differentiate ssl certs virtual bool setHiddenNode(const RsPeerId &id, const std::string &hidden_node_address); virtual bool setHiddenNode(const RsPeerId &id, const std::string &address, uint16_t port); + virtual bool isHiddenNode(const RsPeerId &id); virtual bool setLocalAddress(const RsPeerId &id, const std::string &addr, uint16_t port); virtual bool setExtAddress(const RsPeerId &id, const std::string &addr, uint16_t port); diff --git a/libretroshare/src/services/p3discovery2.cc b/libretroshare/src/services/p3discovery2.cc index 4c08b4abe..4728a0d77 100644 --- a/libretroshare/src/services/p3discovery2.cc +++ b/libretroshare/src/services/p3discovery2.cc @@ -38,7 +38,7 @@ RsDisc *rsDisc = NULL; * #define P3DISC_DEBUG 1 ****/ -bool populateContactInfo(const peerState &detail, RsDiscContactItem *pkt) +static bool populateContactInfo(const peerState &detail, RsDiscContactItem *pkt,bool include_ip_information) { pkt->clear(); @@ -62,14 +62,24 @@ bool populateContactInfo(const peerState &detail, RsDiscContactItem *pkt) { pkt->isHidden = false; - pkt->localAddrV4.addr = detail.localaddr; - pkt->extAddrV4.addr = detail.serveraddr; - sockaddr_storage_clear(pkt->localAddrV6.addr); - sockaddr_storage_clear(pkt->extAddrV6.addr); + if(include_ip_information) + { + pkt->localAddrV4.addr = detail.localaddr; + pkt->extAddrV4.addr = detail.serveraddr; + sockaddr_storage_clear(pkt->localAddrV6.addr); + sockaddr_storage_clear(pkt->extAddrV6.addr); - pkt->dyndns = detail.dyndns; - detail.ipAddrs.mLocal.loadTlv(pkt->localAddrList); - detail.ipAddrs.mExt.loadTlv(pkt->extAddrList); + pkt->dyndns = detail.dyndns; + detail.ipAddrs.mLocal.loadTlv(pkt->localAddrList); + detail.ipAddrs.mExt.loadTlv(pkt->extAddrList); + } + else + { + sockaddr_storage_clear(pkt->localAddrV6.addr); + sockaddr_storage_clear(pkt->extAddrV6.addr); + sockaddr_storage_clear(pkt->localAddrV4.addr); + sockaddr_storage_clear(pkt->extAddrV4.addr); + } } return true; @@ -334,9 +344,8 @@ void p3discovery2::sendOwnContactInfo(const SSLID &sslid) if (mPeerMgr->getOwnNetStatus(detail)) { RsDiscContactItem *pkt = new RsDiscContactItem(); - populateContactInfo(detail, pkt); + populateContactInfo(detail, pkt, !rsPeers->isHiddenNode(sslid)); // we dont send our own IP to an hidden node. It will not use it anyway. pkt->version = RsUtil::retroshareVersion(); - pkt->PeerId(sslid); #ifdef P3DISC_DEBUG @@ -372,6 +381,7 @@ void p3discovery2::recvOwnContactInfo(const SSLID &fromId, const RsDiscContactIt mPeerMgr->setVisState(fromId, item->vs_disc, item->vs_dht); setPeerVersion(fromId, item->version); + updatePeerAddresses(item); // This information will be sent out to online peers, at the receipt of their PGPList. @@ -423,13 +433,10 @@ void p3discovery2::recvOwnContactInfo(const SSLID &fromId, const RsDiscContactIt void p3discovery2::updatePeerAddresses(const RsDiscContactItem *item) { if (item->isHidden) - { mPeerMgr->setHiddenDomainPort(item->sslId, item->hiddenAddr, item->hiddenPort); - } else { mPeerMgr->setDynDNS(item->sslId, item->dyndns); - updatePeerAddressList(item); } } @@ -440,7 +447,7 @@ void p3discovery2::updatePeerAddressList(const RsDiscContactItem *item) if (item->isHidden) { } - else + else if(!mPeerMgr->isHiddenNode(rsPeers->getOwnId())) // we don't store IP addresses if we're a hidden node. Normally they should not be sent to us, except for old peers. { pqiIpAddrSet addrsFromPeer; addrsFromPeer.mLocal.extractFromTlv(item->localAddrList); @@ -817,7 +824,7 @@ void p3discovery2::sendContactInfo_locked(const PGPID &aboutId, const SSLID &toI if (mPeerMgr->getFriendNetStatus(sit->first, detail)) { RsDiscContactItem *pkt = new RsDiscContactItem(); - populateContactInfo(detail, pkt); + populateContactInfo(detail, pkt,!mPeerMgr->isHiddenNode(toId));// never send IPs to an hidden node. The node will not use them anyway. pkt->PeerId(toId); // send to each peer its own connection address. diff --git a/libretroshare/src/turtle/p3turtle.cc b/libretroshare/src/turtle/p3turtle.cc index 9fe58915b..b64001127 100644 --- a/libretroshare/src/turtle/p3turtle.cc +++ b/libretroshare/src/turtle/p3turtle.cc @@ -907,6 +907,7 @@ void p3turtle::handleSearchRequest(RsTurtleSearchRequestItem *item) req.origin = item->PeerId() ; req.time_stamp = time(NULL) ; req.depth = item->depth ; + req.keywords = item->GetKeywords() ; // If it's not for us, perform a local search. If something found, forward the search result back. @@ -1785,6 +1786,10 @@ void RsTurtleRegExpSearchRequestItem::performLocalSearch(std::listtoStdString() << std::endl; +#endif + // now, search! rsFiles->SearchBoolExp(exp,initialResults,RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_SEARCHABLE,PeerId()); @@ -2097,6 +2102,7 @@ void p3turtle::getInfo( std::vector >& hashes_info, info.source_peer_id = it->second.origin ; info.age = now - it->second.time_stamp ; info.depth = it->second.depth ; + info.keywords = it->second.keywords ; search_reqs_info.push_back(info) ; } diff --git a/libretroshare/src/turtle/p3turtle.h b/libretroshare/src/turtle/p3turtle.h index def720cb4..a41317eb2 100644 --- a/libretroshare/src/turtle/p3turtle.h +++ b/libretroshare/src/turtle/p3turtle.h @@ -172,6 +172,7 @@ class TurtleRequestInfo uint32_t time_stamp ; // last time the tunnel was actually used. Used for cleaning old tunnels. int depth ; // depth of the request. Used to optimize tunnel length. std::set responses; // responses to this request. Useful to avoid spamming tunnel responses. + std::string keywords; }; class TurtleTunnel diff --git a/libretroshare/src/turtle/rsturtleitem.h b/libretroshare/src/turtle/rsturtleitem.h index d4d061865..248082652 100644 --- a/libretroshare/src/turtle/rsturtleitem.h +++ b/libretroshare/src/turtle/rsturtleitem.h @@ -71,7 +71,9 @@ class RsTurtleSearchRequestItem: public RsTurtleItem virtual RsTurtleSearchRequestItem *clone() const = 0 ; // used for cloning in routing methods virtual void performLocalSearch(std::list&) const = 0 ; // abstracts the search method - + + virtual std::string GetKeywords() = 0; + uint32_t request_id ; // randomly generated request id. uint16_t depth ; // Used for limiting search depth. }; @@ -82,7 +84,9 @@ class RsTurtleStringSearchRequestItem: public RsTurtleSearchRequestItem RsTurtleStringSearchRequestItem() : RsTurtleSearchRequestItem(RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST) {} std::string match_string ; // string to match - + + std::string GetKeywords() { return match_string; } + virtual RsTurtleSearchRequestItem *clone() const { return new RsTurtleStringSearchRequestItem(*this) ; } virtual void performLocalSearch(std::list&) const ; @@ -99,6 +103,14 @@ class RsTurtleRegExpSearchRequestItem: public RsTurtleSearchRequestItem RsRegularExpression::LinearizedExpression expr ; // Reg Exp in linearised mode + std::string GetKeywords() + { + RsRegularExpression::Expression *ex = RsRegularExpression::LinearizedExpression::toExpr(expr); + std::string exs = ex->toStdString(); + delete ex; + return exs; + } + virtual RsTurtleSearchRequestItem *clone() const { return new RsTurtleRegExpSearchRequestItem(*this) ; } virtual void performLocalSearch(std::list&) const ; diff --git a/libretroshare/src/util/rsdir.cc b/libretroshare/src/util/rsdir.cc index 42e075cdf..900743531 100644 --- a/libretroshare/src/util/rsdir.cc +++ b/libretroshare/src/util/rsdir.cc @@ -104,6 +104,23 @@ const char *RsDirUtil::scanf_string_for_uint(int bytes) return strgs[0] ; } +bool RsDirUtil::splitDirFromFile(const std::string& full_path,std::string& dir, std::string& file) +{ + int i = full_path.rfind('/', full_path.size()-1); + + if(i == full_path.size()-1) // '/' not found! + { + file = full_path ; + dir = "." ; + return true ; + } + + dir.assign(full_path,0,i+1) ; + file.assign(full_path,i+1,full_path.size()) ; + + return true ; +} + void RsDirUtil::removeTopDir(const std::string& dir, std::string& path) { path.clear(); @@ -245,6 +262,19 @@ bool RsDirUtil::fileExists(const std::string& filename) bool RsDirUtil::moveFile(const std::string& source,const std::string& dest) { + // Check that the destination directory exists. If not, create it. + + std::string dest_dir ; + std::string dest_file ; + + splitDirFromFile(dest,dest_dir,dest_file) ; + + std::cerr << "Moving file " << source << " to " << dest << std::endl; + std::cerr << "Checking that directory " << dest_dir << " actually exists." << std::endl; + + if(!checkCreateDirectory(dest_dir)) + return false ; + // First try a rename // @@ -458,7 +488,7 @@ bool RsDirUtil::checkCreateDirectory(const std::string& dir) std::cerr << "check_create_directory() Fatal Error et oui--"; std::cerr < 512) + { + SHA256_Update(&sha_ctx, data, 512); + data = &data[512] ; + size -= 512 ; + } + SHA256_Update(&sha_ctx, data, size); + + unsigned char sha_buf[SHA256_DIGEST_LENGTH]; + SHA256_Final(&sha_buf[0], &sha_ctx); + + return Sha256CheckSum(sha_buf) ; +} bool RsDirUtil::saveStringToFile(const std::string &file, const std::string &str) { std::ofstream out(file.c_str(), std::ios_base::out | std::ios_base::binary); diff --git a/libretroshare/src/util/rsdir.h b/libretroshare/src/util/rsdir.h index 8f52b009f..ef95e100e 100644 --- a/libretroshare/src/util/rsdir.h +++ b/libretroshare/src/util/rsdir.h @@ -83,6 +83,11 @@ const char *scanf_string_for_uint(int bytes) ; int breakupDirList(const std::string& path, std::list &subdirs); +// Splits the path into parent directory and file. File can be empty if full_path is a dir ending with '/' +// if full_path does not contain a directory, then dir will be "." and file will be full_path. + +bool splitDirFromFile(const std::string& full_path,std::string& dir, std::string& file); + bool copyFile(const std::string& source,const std::string& dest); bool moveFile(const std::string& source,const std::string& dest); bool removeFile(const std::string& file); @@ -101,7 +106,8 @@ bool cleanupDirectoryFaster(const std::string& dir, const std::set::iterator iter; switch (Op) { @@ -199,6 +225,17 @@ void LinearizedExpression::readStringExpr(const LinearizedExpression& e,int& n_i strings.push_back(e._strings[n_strings++]) ; } +std::string LinearizedExpression::GetStrings() +{ + std::string str; + for (std::vector::const_iterator i = this->_strings.begin(); i != this->_strings.end(); ++i) + { + str += *i; + str += " "; + } + return str; +} + Expression *LinearizedExpression::toExpr(const LinearizedExpression& e,int& n_tok,int& n_ints,int& n_strings) { LinearizedExpression::token tok = static_cast(e._tokens[n_tok++]) ; diff --git a/openpgpsdk/src/openpgpsdk/packet.h b/openpgpsdk/src/openpgpsdk/packet.h index cbbd3499e..49e59a556 100644 --- a/openpgpsdk/src/openpgpsdk/packet.h +++ b/openpgpsdk/src/openpgpsdk/packet.h @@ -348,7 +348,10 @@ typedef enum // SHA1 Hash Size \todo is this the same as OPS_CHECKHASH_SIZE?? #define OPS_SHA1_HASH_SIZE SHA_DIGEST_LENGTH +#define OPS_SHA224_HASH_SIZE SHA224_DIGEST_LENGTH #define OPS_SHA256_HASH_SIZE SHA256_DIGEST_LENGTH +#define OPS_SHA384_HASH_SIZE SHA384_DIGEST_LENGTH +#define OPS_SHA512_HASH_SIZE SHA512_DIGEST_LENGTH // Max hash size #define OPS_MAX_HASH_SIZE 64 diff --git a/openpgpsdk/src/openpgpsdk/signature.c b/openpgpsdk/src/openpgpsdk/signature.c index 2da7bf087..b62ebdb9f 100644 --- a/openpgpsdk/src/openpgpsdk/signature.c +++ b/openpgpsdk/src/openpgpsdk/signature.c @@ -216,8 +216,49 @@ static ops_boolean_t rsa_sign(ops_hash_t *hash, const ops_rsa_public_key_t *rsa, unsigned t; BIGNUM *bn; + int plen ; + unsigned int hash_length ; + unsigned char *prefix ; + + switch(hash->algorithm) + { + case OPS_HASH_SHA1: hashsize=OPS_SHA1_HASH_SIZE+sizeof prefix_sha1; + hash_length=OPS_SHA1_HASH_SIZE ; + prefix = prefix_sha1; + plen = sizeof prefix_sha1 ; + break ; + + case OPS_HASH_SHA224: hashsize=OPS_SHA224_HASH_SIZE+sizeof prefix_sha224; + hash_length=OPS_SHA224_HASH_SIZE ; + prefix = prefix_sha224; + plen = sizeof prefix_sha224 ; + break ; + + case OPS_HASH_SHA256: hashsize=OPS_SHA256_HASH_SIZE+sizeof prefix_sha256; + hash_length=OPS_SHA256_HASH_SIZE ; + prefix = prefix_sha256; + plen = sizeof prefix_sha256 ; + break ; + + case OPS_HASH_SHA384: hashsize=OPS_SHA384_HASH_SIZE+sizeof prefix_sha384; + hash_length=OPS_SHA384_HASH_SIZE ; + prefix = prefix_sha384; + plen = sizeof prefix_sha384 ; + break ; + + case OPS_HASH_SHA512: hashsize=OPS_SHA512_HASH_SIZE+sizeof prefix_sha512; + hash_length=OPS_SHA512_HASH_SIZE ; + prefix = prefix_sha512; + plen = sizeof prefix_sha512 ; + break ; + + case OPS_HASH_MD5: fprintf(stderr,"(insecure) MD5+RSA signatures not supported in RSA sign") ; + return ops_false ; + + default: fprintf(stderr,"Hash algorithm %d not supported in RSA sign",hash->algorithm) ; + return ops_false ; + } // XXX: we assume hash is sha-1 for now - hashsize=20+sizeof prefix_sha1; keysize=BN_num_bytes(rsa->n); @@ -240,12 +281,12 @@ static ops_boolean_t rsa_sign(ops_hash_t *hash, const ops_rsa_public_key_t *rsa, hashbuf[n]=0xff; hashbuf[n++]=0; - memcpy(&hashbuf[n], prefix_sha1, sizeof prefix_sha1); - n+=sizeof prefix_sha1; + memcpy(&hashbuf[n], prefix, plen); + n+=plen; t=hash->finish(hash, &hashbuf[n]); - if(t != 20) + if(t != hash_length) { fprintf(stderr,"Wrong hash size. Should be 20! can't sign.") ; return ops_false ; @@ -1376,12 +1417,13 @@ void example(const ops_secret_key_t *skey) \endcode */ ops_memory_t* ops_sign_buf(const void* input, const size_t input_len, - const ops_sig_type_t sig_type, - const ops_secret_key_t *skey, - const ops_boolean_t use_armour, - ops_boolean_t include_data, - ops_boolean_t include_creation_time, - ops_boolean_t include_key_id) + const ops_sig_type_t sig_type, + const ops_hash_algorithm_t hash_algorithm, + const ops_secret_key_t *skey, + const ops_boolean_t use_armour, + ops_boolean_t include_data, + ops_boolean_t include_creation_time, + ops_boolean_t include_key_id) { // \todo allow choice of hash algorithams // enforce use of SHA1 for now @@ -1392,7 +1434,7 @@ ops_memory_t* ops_sign_buf(const void* input, const size_t input_len, ops_create_info_t *cinfo=NULL; ops_memory_t *mem=ops_memory_new(); - ops_hash_algorithm_t hash_alg=OPS_HASH_SHA1; + ops_hash_algorithm_t hash_alg=hash_algorithm ; ops_literal_data_type_t ld_type; ops_hash_t* hash=NULL; diff --git a/openpgpsdk/src/openpgpsdk/signature.h b/openpgpsdk/src/openpgpsdk/signature.h index a40c073ff..eb87d0ee5 100644 --- a/openpgpsdk/src/openpgpsdk/signature.h +++ b/openpgpsdk/src/openpgpsdk/signature.h @@ -90,7 +90,7 @@ void ops_signature_add_primary_user_id(ops_create_signature_t *sig, ops_boolean_t ops_sign_file_as_cleartext(const char* input_filename, const char* output_filename, const ops_secret_key_t *skey, const ops_boolean_t overwrite); ops_boolean_t ops_sign_buf_as_cleartext(const char* input, const size_t len, ops_memory_t** output, const ops_secret_key_t *skey); ops_boolean_t ops_sign_file(const char* input_filename, const char* output_filename, const ops_secret_key_t *skey, const ops_boolean_t use_armour, const ops_boolean_t overwrite); -ops_memory_t * ops_sign_buf(const void* input, const size_t input_len, const ops_sig_type_t sig_type, const ops_secret_key_t *skey, const ops_boolean_t use_armour,ops_boolean_t include_data,ops_boolean_t include_creation_time,ops_boolean_t include_key_id); +ops_memory_t * ops_sign_buf(const void* input, const size_t input_len, const ops_sig_type_t sig_type, const ops_hash_algorithm_t hash_algorithm, const ops_secret_key_t *skey, const ops_boolean_t use_armour, ops_boolean_t include_data, ops_boolean_t include_creation_time, ops_boolean_t include_key_id); ops_boolean_t ops_writer_push_signed(ops_create_info_t *cinfo, const ops_sig_type_t sig_type, const ops_secret_key_t *skey); #endif diff --git a/plugins/FeedReader/FeedReader.pro b/plugins/FeedReader/FeedReader.pro index 022412a3f..7e7e40fdd 100644 --- a/plugins/FeedReader/FeedReader.pro +++ b/plugins/FeedReader/FeedReader.pro @@ -116,10 +116,10 @@ macx { } } } - DEPENDPATH += . $$INC_DIRs + DEPENDPATH += . $$INC_DIR INCLUDEPATH += . $$INC_DIR - LIBS = -lcurl -lxml2 -lxslt -lcrypto + LIBS += -lcurl -lxml2 -lxslt -lcrypto } openbsd-* { diff --git a/retroshare-gui/src/gui/ChatLobbyWidget.cpp b/retroshare-gui/src/gui/ChatLobbyWidget.cpp index d36602f64..5fc3436e1 100644 --- a/retroshare-gui/src/gui/ChatLobbyWidget.cpp +++ b/retroshare-gui/src/gui/ChatLobbyWidget.cpp @@ -1078,17 +1078,38 @@ void ChatLobbyWidget::readChatLobbyInvites() RsGxsId default_id ; rsMsgs->getDefaultIdentityForChatLobby(default_id) ; + std::list subscribed_lobbies ; + rsMsgs->getChatLobbyList(subscribed_lobbies) ; + for(std::list::const_iterator it(invites.begin());it!=invites.end();++it) { + // first check if the lobby is already subscribed. If so, just ignore the request. + + bool found = false ; + for(auto it2(subscribed_lobbies.begin());it2!=subscribed_lobbies.end() && !found;++it2) + found = found || (*it2 == (*it).lobby_id) ; + + if(found) + continue ; + QMessageBox mb(QObject::tr("Join chat room"), tr("%1 invites you to chat room named %2").arg(QString::fromUtf8(rsPeers->getPeerName((*it).peer_id).c_str())).arg(RsHtml::plainText(it->lobby_name)), QMessageBox::Question, QMessageBox::Yes,QMessageBox::No, 0); - QLabel *label = new QLabel(tr("Choose an identity for this chat room:")); + QLabel *label ; GxsIdChooser *idchooser = new GxsIdChooser ; - idchooser->loadIds(IDCHOOSER_ID_REQUIRED,default_id) ; + if( (*it).lobby_flags & RS_CHAT_LOBBY_FLAGS_PGP_SIGNED ) + { + idchooser->loadIds(IDCHOOSER_ID_REQUIRED | IDCHOOSER_NON_ANONYMOUS,default_id) ; + label = new QLabel(tr("Choose a non anonymous identity for this chat room:")); + } + else + { + idchooser->loadIds(IDCHOOSER_ID_REQUIRED,default_id) ; + label = new QLabel(tr("Choose an identity for this chat room:")); + } QGridLayout* layout = qobject_cast(mb.layout()); if (layout) { diff --git a/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp b/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp index d55f78e99..ee85a1d92 100644 --- a/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp @@ -445,10 +445,10 @@ void SearchDialog::collCreate() details.type = DIR_TYPE_FILE; dirVec.push_back(details); - }//if (!item->text(SR_HASH_COL).isEmpty()) - }//for (int i = 0; i < numdls; ++i) + } + } - RsCollection(dirVec).openNewColl(this); + RsCollection(dirVec,RS_FILE_HINTS_LOCAL).openNewColl(this); } void SearchDialog::collModif() @@ -795,8 +795,7 @@ void SearchDialog::advancedSearch(RsRegularExpression::Expression* expression) TurtleRequestId req_id = rsTurtle->turtleSearch(e) ; // This will act before turtle results come to the interface, thanks to the signals scheduling policy. - // The text "bool exp" should be replaced by an appropriate text describing the actual search. - initSearchResult("bool exp",req_id, ui.FileTypeComboBox->currentIndex(), true) ; + initSearchResult(QString::fromStdString(e.GetStrings()),req_id, ui.FileTypeComboBox->currentIndex(), true) ; rsFiles -> SearchBoolExp(expression, results, RS_FILE_HINTS_REMOTE);// | DIR_FLAGS_NETWORK_WIDE | DIR_FLAGS_BROWSABLE); diff --git a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp index bf3e1c92b..ce67043a9 100644 --- a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp @@ -509,9 +509,20 @@ void RemoteSharedFilesDialog::spawnCustomPopupMenu( QPoint point ) collectionMenu.addAction(collCreateAct); collectionMenu.addAction(collOpenAct); - QAction *downloadAct = new QAction(QIcon(IMAGE_DOWNLOAD), tr( "Download" ), &contextMnu ) ; - connect( downloadAct , SIGNAL( triggered() ), this, SLOT( downloadRemoteSelected() ) ) ; - contextMnu.addAction( downloadAct) ; + QModelIndexList list = ui.dirTreeView->selectionModel()->selectedRows() ; + + if(type == DIR_TYPE_DIR || list.size() > 1) + { + QAction *downloadActI = new QAction(QIcon(IMAGE_DOWNLOAD), tr( "Download..." ), &contextMnu ) ; + connect( downloadActI , SIGNAL( triggered() ), this, SLOT( downloadRemoteSelectedInteractive() ) ) ; + contextMnu.addAction( downloadActI) ; + } + else + { + QAction *downloadAct = new QAction(QIcon(IMAGE_DOWNLOAD), tr( "Download" ), &contextMnu ) ; + connect( downloadAct , SIGNAL( triggered() ), this, SLOT( downloadRemoteSelected() ) ) ; + contextMnu.addAction( downloadAct) ; + } contextMnu.addSeparator() ;//------------------------------------ contextMnu.addAction( copylinkAct) ; @@ -545,7 +556,16 @@ void RemoteSharedFilesDialog::expanded(const QModelIndex& indx) model->updateRef(proxyModel->mapToSource(indx)) ; } +void RemoteSharedFilesDialog::downloadRemoteSelectedInteractive() +{ + /* call back to the model (which does all the interfacing? */ + std::cerr << "Downloading Files" ; + std::cerr << std::endl ; + + QModelIndexList lst = getSelected() ; + model -> downloadSelected(lst,true) ; +} void RemoteSharedFilesDialog::downloadRemoteSelected() { /* call back to the model (which does all the interfacing? */ @@ -554,7 +574,7 @@ void RemoteSharedFilesDialog::downloadRemoteSelected() std::cerr << std::endl ; QModelIndexList lst = getSelected() ; - model -> downloadSelected(lst) ; + model -> downloadSelected(lst,false) ; } void SharedFilesDialog::copyLinks(const QModelIndexList& lst, bool remote,QList& urls,bool& has_unhashed_files) diff --git a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.h b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.h index 8e242a0a6..4fb18ab0c 100644 --- a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.h +++ b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.h @@ -187,6 +187,7 @@ class RemoteSharedFilesDialog : public SharedFilesDialog private slots: void downloadRemoteSelected(); + void downloadRemoteSelectedInteractive(); void expanded(const QModelIndex& indx); }; diff --git a/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp b/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp index ea06b598b..196bc90ac 100644 --- a/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp @@ -2133,7 +2133,8 @@ void TransfersDialog::collCreate() std::set::iterator it ; getDLSelectedItems(&items, NULL); - for (it = items.begin(); it != items.end(); ++it) { + for (it = items.begin(); it != items.end(); ++it) + { FileInfo info; if (!rsFiles->FileDetails(*it, RS_FILE_HINTS_DOWNLOAD, info)) continue; @@ -2144,9 +2145,9 @@ void TransfersDialog::collCreate() details.type = DIR_TYPE_FILE; dirVec.push_back(details); - }//for (it = items.begin(); + } - RsCollection(dirVec).openNewColl(this); + RsCollection(dirVec,RS_FILE_HINTS_LOCAL).openNewColl(this); } void TransfersDialog::collModif() diff --git a/retroshare-gui/src/gui/Identity/IdDialog.cpp b/retroshare-gui/src/gui/Identity/IdDialog.cpp index 2ce051d3c..065a7cb66 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.cpp +++ b/retroshare-gui/src/gui/Identity/IdDialog.cpp @@ -23,6 +23,7 @@ #include +#include #include #include #include @@ -32,21 +33,23 @@ #include "IdDialog.h" #include "ui_IdDialog.h" #include "IdEditDialog.h" -#include "retroshare-gui/RsAutoUpdatePage.h" +#include "gui/RetroShareLink.h" +#include "gui/chat/ChatDialog.h" +#include "gui/Circles/CreateCircleDialog.h" +#include "gui/common/UIStateHelper.h" #include "gui/gxs/GxsIdDetails.h" #include "gui/gxs/RsGxsUpdateBroadcastBase.h" -#include "gui/common/UIStateHelper.h" -#include "gui/chat/ChatDialog.h" -#include "gui/settings/rsharesettings.h" #include "gui/msgs/MessageComposer.h" -#include "gui/Circles/CreateCircleDialog.h" -#include "gui/RetroShareLink.h" +#include "gui/settings/rsharesettings.h" +#include "retroshare-gui/RsAutoUpdatePage.h" +#include "util/misc.h" #include "util/QtVersion.h" -#include #include "retroshare/rsgxsflags.h" #include "retroshare/rsmsgs.h" +#include "retroshare/rspeers.h" #include "retroshare/rsservicecontrol.h" + #include #include @@ -175,32 +178,40 @@ IdDialog::IdDialog(QWidget *parent) : mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_Nickname); mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_KeyId); -// mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_GpgHash); + mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_Type); mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_GpgId); mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_GpgName); - mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_Type); mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_LastUsed); mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->ownOpinion_CB); - mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->overallOpinion_TF); + mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->autoBanIdentities_CB); mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->neighborNodesOpinion_TF); + mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->overallOpinion_TF); + mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->usageStatistics_TB); + mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->inviteButton); + mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->label_positive); + mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->label_negative); mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_Nickname); - mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_GpgName); mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_KeyId); -// mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_GpgHash); - mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_GpgId); mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_Type); + mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_GpgId); mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_GpgName); mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_LastUsed); - //mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->line_RatingOverall); + mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->neighborNodesOpinion_TF); + mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->overallOpinion_TF); + mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->usageStatistics_TB); mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_Nickname); mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_KeyId); -// mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_GpgHash); - mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_GpgId); mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_Type); + mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_GpgId); mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_GpgName); mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_LastUsed); + mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->neighborNodesOpinion_TF); + mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->overallOpinion_TF); + mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->usageStatistics_TB); + mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->label_positive); + mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->label_negative); //mStateHelper->addWidget(IDDIALOG_REPLIST, ui->treeWidget_RepList); //mStateHelper->addLoadPlaceholder(IDDIALOG_REPLIST, ui->treeWidget_RepList); @@ -221,22 +232,15 @@ IdDialog::IdDialog(QWidget *parent) : connect(ui->inviteButton, SIGNAL(clicked()), this, SLOT(sendInvite())); - ui->avLabel_Person->setPixmap(QPixmap(":/icons/png/people.png")); ui->avlabel_Circles->setPixmap(QPixmap(":/icons/png/circles.png")); - ui->headerTextLabel_Person->setText(tr("People")); ui->headerTextLabel_Circles->setText(tr("Circles")); /* Initialize splitter */ ui->mainSplitter->setStretchFactor(0, 0); ui->mainSplitter->setStretchFactor(1, 1); - ui->inviteFrame->hide(); - - /*remove - QList sizes; - sizes << width() << 500; // Qt calculates the right sizes - ui->splitter->setSizes(sizes);*/ + clearPerson(); /* Add filter types */ QMenu *idTWHMenu = new QMenu(tr("Show Items"), this); @@ -385,7 +389,22 @@ IdDialog::IdDialog(QWidget *parent) : connect(tmer,SIGNAL(timeout()),this,SLOT(updateCirclesDisplay())) ; tmer->start(10000) ; // update every 10 secs. -} +} + +void IdDialog::clearPerson() +{ + QFontMetricsF f(ui->avLabel_Person->font()) ; + + ui->avLabel_Person->setPixmap(QPixmap(":/icons/png/people.png").scaled(f.height()*4,f.height()*4,Qt::IgnoreAspectRatio,Qt::SmoothTransformation)); + ui->headerTextLabel_Person->setText(tr("People")); + + ui->inviteFrame->hide(); + ui->avatarLabel->clear(); + + whileBlocking(ui->ownOpinion_CB)->setCurrentIndex(1); + whileBlocking(ui->autoBanIdentities_CB)->setChecked(false); + +} void IdDialog::toggleAutoBanIdentities(bool b) { @@ -1582,9 +1601,9 @@ void IdDialog::insertIdList(uint32_t token) int accept = filter; - RsGxsIdGroup data; + //RsGxsIdGroup data; std::vector datavector; - std::vector::iterator vit; + //std::vector::iterator vit; if (!rsIdentity->getGroupData(token, datavector)) { @@ -1595,6 +1614,7 @@ void IdDialog::insertIdList(uint32_t token) mStateHelper->setActive(IDDIALOG_IDLIST, false); mStateHelper->clear(IDDIALOG_IDLIST); + clearPerson(); return; } @@ -1645,8 +1665,8 @@ void IdDialog::insertIdList(uint32_t token) /* Insert new items */ for (std::map::const_iterator vit = ids_set.begin(); vit != ids_set.end(); ++vit) - { - data = vit->second ; + { + RsGxsIdGroup data = vit->second ; item = NULL; @@ -1661,16 +1681,16 @@ void IdDialog::insertIdList(uint32_t token) Settings->endGroup(); - if (fillIdListItem(vit->second, item, ownPgpId, accept)) - { - if(vit->second.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) - ownItem->addChild(item); - else if(vit->second.mIsAContact) - contactsItem->addChild(item); - else - allItem->addChild(item); - } - } + if (fillIdListItem(data, item, ownPgpId, accept)) + { + if(data.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) + ownItem->addChild(item); + else if(data.mIsAContact) + contactsItem->addChild(item); + else + allItem->addChild(item); + } + } /* count items */ int itemCount = contactsItem->childCount() + allItem->childCount() + ownItem->childCount(); @@ -1690,6 +1710,7 @@ void IdDialog::requestIdDetails() mStateHelper->setActive(IDDIALOG_IDDETAILS, false); mStateHelper->setLoading(IDDIALOG_IDDETAILS, false); mStateHelper->clear(IDDIALOG_IDDETAILS); + clearPerson(); return; } @@ -1717,6 +1738,7 @@ void IdDialog::insertIdDetails(uint32_t token) { mStateHelper->setActive(IDDIALOG_IDDETAILS, false); mStateHelper->clear(IDDIALOG_REPLIST); + clearPerson(); ui->lineEdit_KeyId->setText("ERROR GETTING KEY!"); @@ -1731,6 +1753,7 @@ void IdDialog::insertIdDetails(uint32_t token) mStateHelper->setActive(IDDIALOG_IDDETAILS, false); mStateHelper->clear(IDDIALOG_IDDETAILS); + clearPerson(); ui->lineEdit_KeyId->setText("INVALID DV SIZE"); @@ -1768,8 +1791,14 @@ void IdDialog::insertIdDetails(uint32_t token) std::cerr << "Setting header frame image : " << pixmap.width() << " x " << pixmap.height() << std::endl; #endif - ui->avLabel_Person->setPixmap(pixmap); - ui->avatarLabel->setPixmap(pixmap); + //ui->avLabel_Person->setPixmap(pixmap); + //ui->avatarLabel->setPixmap(pixmap); + QFontMetricsF f(ui->avLabel_Person->font()) ; + ui->avLabel_Person->setPixmap(pixmap.scaled(f.height()*4,f.height()*4,Qt::KeepAspectRatio,Qt::SmoothTransformation)); + + QFontMetricsF g(ui->inviteButton->font()) ; + ui->avatarLabel->setPixmap(pixmap.scaled(ui->inviteButton->width(),ui->inviteButton->width(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation)); + ui->avatarLabel->setScaledContents(true); if (data.mPgpKnown) { @@ -1814,7 +1843,10 @@ void IdDialog::insertIdDetails(uint32_t token) if (isLinkedToOwnPgpId) ui->lineEdit_Type->setText(tr("Identity owned by you, linked to your Retroshare node")) ; else - ui->lineEdit_Type->setText(tr("Anonymous identity, owned by you")) ; + if (data.mMeta.mGroupFlags & (GXS_SERV::FLAG_PRIVACY_PRIVATE | RSGXSID_GROUPFLAG_REALID)) + ui->lineEdit_Type->setText(tr("Identity owned by you, linked to your Retroshare node but not yet validated")) ; + else + ui->lineEdit_Type->setText(tr("Anonymous identity, owned by you")) ; else if (data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility) { if (data.mPgpKnown) diff --git a/retroshare-gui/src/gui/Identity/IdDialog.h b/retroshare-gui/src/gui/Identity/IdDialog.h index fe2cb058c..1037510f1 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.h +++ b/retroshare-gui/src/gui/Identity/IdDialog.h @@ -138,6 +138,8 @@ private: void requestIdEdit(std::string &id); void showIdEdit(uint32_t token); + void clearPerson(); + private: TokenQueue *mIdQueue; TokenQueue *mCircleQueue; diff --git a/retroshare-gui/src/gui/Identity/IdDialog.ui b/retroshare-gui/src/gui/Identity/IdDialog.ui index b75154361..4e449cfa0 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.ui +++ b/retroshare-gui/src/gui/Identity/IdDialog.ui @@ -290,6 +290,12 @@ + + + 0 + 0 + + QFrame::StyledPanel @@ -477,6 +483,12 @@ border-image: url(:/images/closepressed.png) + + + 0 + 0 + + 64 @@ -485,8 +497,8 @@ border-image: url(:/images/closepressed.png) - 64 - 64 + 1000 + 1000 diff --git a/retroshare-gui/src/gui/Identity/IdEditDialog.cpp b/retroshare-gui/src/gui/Identity/IdEditDialog.cpp index a8212f426..8bddb1be6 100644 --- a/retroshare-gui/src/gui/Identity/IdEditDialog.cpp +++ b/retroshare-gui/src/gui/Identity/IdEditDialog.cpp @@ -227,6 +227,7 @@ void IdEditDialog::enforceNoAnonIds() { ui->radioButton_GpgId->setChecked(true); ui->radioButton_GpgId->setEnabled(false); + ui->radioButton_Pseudo->setEnabled(false); } void IdEditDialog::loadExistingId(uint32_t token) diff --git a/retroshare-gui/src/gui/MainWindow.cpp b/retroshare-gui/src/gui/MainWindow.cpp index cc08d4954..35399146a 100644 --- a/retroshare-gui/src/gui/MainWindow.cpp +++ b/retroshare-gui/src/gui/MainWindow.cpp @@ -1027,12 +1027,12 @@ void MainWindow::addFriend() } /** New RSCollection ShortCut */ -void MainWindow::newRsCollection() -{ - std::vector dirVec; - - RsCollection(dirVec).openNewColl(this); -} +// void MainWindow::newRsCollection() +// { +// std::vector dirVec; +// +// RsCollection(dirVec).openNewColl(this); +// } /** Shows Share Manager */ void MainWindow::openShareManager() diff --git a/retroshare-gui/src/gui/MainWindow.h b/retroshare-gui/src/gui/MainWindow.h index b3fc246dc..a52bf0073 100644 --- a/retroshare-gui/src/gui/MainWindow.h +++ b/retroshare-gui/src/gui/MainWindow.h @@ -223,7 +223,7 @@ private slots: /** Toolbar fns. */ void addFriend(); - void newRsCollection(); + //void newRsCollection(); void showMessengerWindow(); void showStatisticsWindow(); #ifdef ENABLE_WEBUI diff --git a/retroshare-gui/src/gui/MessagesDialog.cpp b/retroshare-gui/src/gui/MessagesDialog.cpp index ba20eefe8..3735da5aa 100644 --- a/retroshare-gui/src/gui/MessagesDialog.cpp +++ b/retroshare-gui/src/gui/MessagesDialog.cpp @@ -231,7 +231,7 @@ MessagesDialog::MessagesDialog(QWidget *parent) QMenu *printmenu = new QMenu(); printmenu->addAction(ui.actionPrint); printmenu->addAction(ui.actionPrintPreview); - ui.printbutton->setMenu(printmenu); + ui.printButton->setMenu(printmenu); QMenu *viewmenu = new QMenu(); viewmenu->addAction(ui.actionTextBesideIcon); @@ -346,9 +346,8 @@ void MessagesDialog::processSettings(bool load) } // state of splitter - ui.msgSplitter->restoreState(Settings->value("Splitter").toByteArray()); - ui.msgSplitter_2->restoreState(Settings->value("Splitter2").toByteArray()); - ui.listSplitter->restoreState(Settings->value("Splitter3").toByteArray()); + ui.msgSplitter->restoreState(Settings->value("SplitterMsg").toByteArray()); + ui.listSplitter->restoreState(Settings->value("SplitterList").toByteArray()); /* toolbar button style */ Qt::ToolButtonStyle style = (Qt::ToolButtonStyle) Settings->value("ToolButon_Style", Qt::ToolButtonIconOnly).toInt(); @@ -361,9 +360,8 @@ void MessagesDialog::processSettings(bool load) Settings->setValue("MessageTreeVersion", messageTreeVersion); // state of splitter - Settings->setValue("Splitter", ui.msgSplitter->saveState()); - Settings->setValue("Splitter2", ui.msgSplitter_2->saveState()); - Settings->setValue("Splitter3", ui.listSplitter->saveState()); + Settings->setValue("SplitterMsg", ui.msgSplitter->saveState()); + Settings->setValue("SplitterList", ui.listSplitter->saveState()); /* toolbar button style */ Settings->setValue("ToolButon_Style", ui.newmessageButton->toolButtonStyle()); @@ -1527,8 +1525,8 @@ void MessagesDialog::insertMsgTxtAndFiles(QTreeWidgetItem *item, bool bSetToRead } } - msgWidget->fill(mCurrMsgId); updateInterface(); + msgWidget->fill(mCurrMsgId); } bool MessagesDialog::getCurrentMsg(std::string &cid, std::string &mid) @@ -1607,7 +1605,7 @@ void MessagesDialog::setToolbarButtonStyle(Qt::ToolButtonStyle style) ui.replyallmessageButton->setToolButtonStyle(style); ui.forwardmessageButton->setToolButtonStyle(style); ui.tagButton->setToolButtonStyle(style); - ui.printbutton->setToolButtonStyle(style); + ui.printButton->setToolButtonStyle(style); ui.viewtoolButton->setToolButtonStyle(style); } @@ -1710,23 +1708,23 @@ void MessagesDialog::updateMessageSummaryList() { case ROW_INBOX: textTotal = tr("Total:") + " " + QString::number(inboxCount); - ui.total_label->setText(textTotal); + ui.totalLabel->setText(textTotal); break; case ROW_OUTBOX: textTotal = tr("Total:") + " " + QString::number(newOutboxCount); - ui.total_label->setText(textTotal); + ui.totalLabel->setText(textTotal); break; case ROW_DRAFTBOX: textTotal = tr("Total:") + " " + QString::number(newDraftCount); - ui.total_label->setText(textTotal); + ui.totalLabel->setText(textTotal); break; case ROW_SENTBOX: textTotal = tr("Total:") + " " + QString::number(newSentboxCount); - ui.total_label->setText(textTotal); + ui.totalLabel->setText(textTotal); break; case ROW_TRASHBOX: textTotal = tr("Total:") + " " + QString::number(trashboxCount); - ui.total_label->setText(textTotal); + ui.totalLabel->setText(textTotal); break; } @@ -1967,7 +1965,7 @@ void MessagesDialog::connectActions() ui.replymessageButton->disconnect(); ui.replyallmessageButton->disconnect(); ui.forwardmessageButton->disconnect(); - ui.printbutton->disconnect(); + ui.printButton->disconnect(); ui.actionPrint->disconnect(); ui.actionPrintPreview->disconnect(); ui.actionSaveAs->disconnect(); @@ -1994,7 +1992,7 @@ void MessagesDialog::connectActions() msg->connectAction(MessageWidget::ACTION_REPLY, ui.replymessageButton); msg->connectAction(MessageWidget::ACTION_REPLY_ALL, ui.replyallmessageButton); msg->connectAction(MessageWidget::ACTION_FORWARD, ui.forwardmessageButton); - msg->connectAction(MessageWidget::ACTION_PRINT, ui.printbutton); + msg->connectAction(MessageWidget::ACTION_PRINT, ui.printButton); msg->connectAction(MessageWidget::ACTION_PRINT, ui.actionPrint); msg->connectAction(MessageWidget::ACTION_PRINT_PREVIEW, ui.actionPrintPreview); msg->connectAction(MessageWidget::ACTION_SAVE_AS, ui.actionSaveAs); @@ -2019,7 +2017,7 @@ void MessagesDialog::updateInterface() ui.replymessageButton->setEnabled(count == 1); ui.replyallmessageButton->setEnabled(count == 1); ui.forwardmessageButton->setEnabled(count == 1); - ui.printbutton->setEnabled(count == 1); + ui.printButton->setEnabled(count == 1); ui.actionPrint->setEnabled(count == 1); ui.actionPrintPreview->setEnabled(count == 1); ui.actionSaveAs->setEnabled(count == 1); diff --git a/retroshare-gui/src/gui/MessagesDialog.ui b/retroshare-gui/src/gui/MessagesDialog.ui index e3e33b670..1203a1eb2 100644 --- a/retroshare-gui/src/gui/MessagesDialog.ui +++ b/retroshare-gui/src/gui/MessagesDialog.ui @@ -49,7 +49,7 @@ QFrame::Sunken - + 2 @@ -66,7 +66,7 @@ 6 - + Qt::Vertical @@ -219,7 +219,7 @@ - + 0 @@ -454,7 +454,7 @@ Qt::NoFocus - + :/icons/help_64.png:/icons/help_64.png @@ -466,7 +466,7 @@ - + Qt::Horizontal @@ -479,7 +479,7 @@ - + Qt::Horizontal @@ -495,7 +495,7 @@ - + Qt::Vertical @@ -513,7 +513,7 @@ Main Tab - + 0 @@ -535,7 +535,7 @@ Qt::Horizontal - + 0 @@ -629,7 +629,7 @@ - + 0 @@ -646,7 +646,7 @@ true - + 3 @@ -687,7 +687,7 @@ QFrame::Raised - + 3 @@ -726,38 +726,33 @@ Qt::Vertical - - - Qt::Vertical + + + Qt::CustomContextMenu - - - Qt::CustomContextMenu + + QAbstractItemView::ExtendedSelection + + + false + + + true + + + true + + + false + + + + 1 - - QAbstractItemView::ExtendedSelection - - - false - - - true - - - true - - - false - - - - 1 - - - - - - + + + + @@ -838,6 +833,11 @@ + + StyledLabel + QLabel +
gui/common/StyledLabel.h
+
LineEditClear QLineEdit @@ -854,19 +854,14 @@
gui/common/RSTabWidget.h
1
- - StyledLabel - QLabel -
gui/common/StyledLabel.h
-
replymessageButton listWidget - + diff --git a/retroshare-gui/src/gui/NetworkDialog.cpp b/retroshare-gui/src/gui/NetworkDialog.cpp index bdeda264c..e9e305ca8 100644 --- a/retroshare-gui/src/gui/NetworkDialog.cpp +++ b/retroshare-gui/src/gui/NetworkDialog.cpp @@ -58,108 +58,90 @@ #define IMAGE_MESSAGE ":/images/mail_new.png" /* Images for Status icons */ -#define IMAGE_AUTHED ":/images/accepted16.png" + +//following defined in model +/*#define IMAGE_AUTHED ":/images/accepted16.png" #define IMAGE_DENIED ":/images/denied16.png" -#define IMAGE_TRUSTED ":/images/rs-2.png" +#define IMAGE_TRUSTED ":/images/rs-2.png" */ // Defines for key list columns -#define COLUMN_CHECK 0 + +//following defined in model +/*#define COLUMN_CHECK 0 #define COLUMN_PEERNAME 1 #define COLUMN_I_AUTH_PEER 2 #define COLUMN_PEER_AUTH_ME 3 #define COLUMN_PEERID 4 #define COLUMN_LAST_USED 5 -#define COLUMN_COUNT 6 +#define COLUMN_COUNT 6 */ -RsPeerId getNeighRsCertId(QTreeWidgetItem *i); +//RsPeerId getNeighRsCertId(QTreeWidgetItem *i); /****** * #define NET_DEBUG 1 *****/ -static const unsigned int ROLE_SORT = Qt::UserRole + 1 ; +//static const unsigned int ROLE_SORT = Qt::UserRole + 1 ; /** Constructor */ NetworkDialog::NetworkDialog(QWidget *parent) -: RsAutoUpdatePage(10000,parent) // updates every 10 sec. { /* Invoke the Qt Designer generated object setup routine */ + Q_UNUSED(parent); ui.setupUi(this); - connect( ui.connectTreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( connectTreeWidgetCostumPopupMenu( QPoint ) ) ); - connect( ui.connectTreeWidget, SIGNAL( itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT( peerdetails () ) ); - connect( ui.filterLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(filterItems(QString))); connect( ui.filterLineEdit, SIGNAL(filterChanged(int)), this, SLOT(filterColumnChanged(int))); - connect( ui.onlyTrustedKeys, SIGNAL(clicked()), this, SLOT(securedUpdateDisplay())); - /* hide the Tree +/- */ - ui.connectTreeWidget -> setRootIsDecorated( false ); - ui.connectTreeWidget -> setColumnCount(6); + //list data model + float f = QFontMetricsF(font()).height()/14.0 ; - compareNetworkRole = new RSTreeWidgetItemCompareRole; - compareNetworkRole->setRole(COLUMN_LAST_USED, ROLE_SORT); + PGPIdItemModel = new pgpid_item_model(neighs, f, this); + PGPIdItemProxy = new pgpid_item_proxy(this); + connect(ui.onlyTrustedKeys, SIGNAL(toggled(bool)), PGPIdItemProxy, SLOT(use_only_trusted_keys(bool))); + PGPIdItemProxy->setSourceModel(PGPIdItemModel); + PGPIdItemProxy->setFilterKeyColumn(COLUMN_PEERNAME); + PGPIdItemProxy->setFilterCaseSensitivity(Qt::CaseInsensitive); + PGPIdItemProxy->setSortRole(Qt::EditRole); //use edit role to get raw data since we do not have edit for this model. + ui.connectTreeWidget->setModel(PGPIdItemProxy); + ui.connectTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu); + ui.connectTreeWidget->verticalHeader()->hide(); + ui.connectTreeWidget->setShowGrid(false); + ui.connectTreeWidget->setUpdatesEnabled(true); + ui.connectTreeWidget->setSortingEnabled(true); + ui.connectTreeWidget->setSelectionBehavior(QAbstractItemView::SelectRows); + ui.connectTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection); + connect(ui.connectTreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( connectTreeWidgetCostumPopupMenu( QPoint ) ) ); + connect(ui.connectTreeWidget, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(peerdetails())); /* Set header resize modes and initial section sizes */ - QHeaderView * _header = ui.connectTreeWidget->header () ; +/* QHeaderView * _header = ui.connectTreeWidget->header () ; QHeaderView_setSectionResizeModeColumn(_header, COLUMN_CHECK, QHeaderView::Custom); QHeaderView_setSectionResizeModeColumn(_header, COLUMN_PEERNAME, QHeaderView::Interactive); QHeaderView_setSectionResizeModeColumn(_header, COLUMN_I_AUTH_PEER, QHeaderView::Interactive); QHeaderView_setSectionResizeModeColumn(_header, COLUMN_PEER_AUTH_ME, QHeaderView::Interactive); QHeaderView_setSectionResizeModeColumn(_header, COLUMN_PEERID, QHeaderView::Interactive); - QHeaderView_setSectionResizeModeColumn(_header, COLUMN_LAST_USED, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(_header, COLUMN_LAST_USED, QHeaderView::Interactive); */ - _header->model()->setHeaderData(COLUMN_CHECK, Qt::Horizontal, tr("")); - _header->model()->setHeaderData(COLUMN_PEERNAME, Qt::Horizontal, tr("Profile")); - _header->model()->setHeaderData(COLUMN_I_AUTH_PEER, Qt::Horizontal, tr("Trust level")); - _header->model()->setHeaderData(COLUMN_PEER_AUTH_ME, Qt::Horizontal, tr("Has signed your key?")); - _header->model()->setHeaderData(COLUMN_PEERID, Qt::Horizontal, tr("Id")); - _header->model()->setHeaderData(COLUMN_LAST_USED, Qt::Horizontal, tr("Last used")); - - _header->model()->setHeaderData(COLUMN_CHECK, Qt::Horizontal, tr(" Do you accept connections signed by this profile?"),Qt::ToolTipRole); - _header->model()->setHeaderData(COLUMN_PEERNAME, Qt::Horizontal, tr("Name of the profile"),Qt::ToolTipRole); - _header->model()->setHeaderData(COLUMN_I_AUTH_PEER, Qt::Horizontal, tr("This column indicates trust level and whether you signed the profile PGP key"),Qt::ToolTipRole); - _header->model()->setHeaderData(COLUMN_PEER_AUTH_ME, Qt::Horizontal, tr("Did that peer sign your own profile PGP key"),Qt::ToolTipRole); - _header->model()->setHeaderData(COLUMN_PEERID, Qt::Horizontal, tr("PGP Key Id of that profile"),Qt::ToolTipRole); - _header->model()->setHeaderData(COLUMN_LAST_USED, Qt::Horizontal, tr("Last time this key was used (received time, or to check connection)"),Qt::ToolTipRole); - - float f = QFontMetricsF(font()).height()/14.0 ; - - _header->resizeSection ( COLUMN_CHECK, 25*f ); - _header->resizeSection ( COLUMN_PEERNAME, 200*f ); - _header->resizeSection ( COLUMN_I_AUTH_PEER, 200*f ); - _header->resizeSection ( COLUMN_PEER_AUTH_ME, 200*f ); - _header->resizeSection ( COLUMN_LAST_USED, 75*f ); - - // set header text aligment - QTreeWidgetItem * headerItem = ui.connectTreeWidget->headerItem(); - headerItem->setTextAlignment(COLUMN_CHECK, Qt::AlignHCenter | Qt::AlignVCenter); - headerItem->setTextAlignment(COLUMN_PEERNAME, Qt::AlignHCenter | Qt::AlignVCenter); - headerItem->setTextAlignment(COLUMN_I_AUTH_PEER, Qt::AlignHCenter | Qt::AlignVCenter); - headerItem->setTextAlignment(COLUMN_PEER_AUTH_ME, Qt::AlignHCenter | Qt::AlignVCenter); - headerItem->setTextAlignment(COLUMN_PEERID, Qt::AlignVCenter); - headerItem->setTextAlignment(COLUMN_LAST_USED, Qt::AlignVCenter); - - headerItem->setText(0,QString()) ; - - ui.connectTreeWidget->sortItems( COLUMN_PEERNAME, Qt::AscendingOrder ); ui.onlyTrustedKeys->setMinimumWidth(20*f); - QMenu *menu = new QMenu(); +/* QMenu *menu = new QMenu(); menu->addAction(ui.actionTabsright); menu->addAction(ui.actionTabswest); menu->addAction(ui.actionTabssouth); menu->addAction(ui.actionTabsnorth); menu->addSeparator(); menu->addAction(ui.actionTabsTriangular); - menu->addAction(ui.actionTabsRounded); + menu->addAction(ui.actionTabsRounded); */ /* add filter actions */ ui.filterLineEdit->addFilter(QIcon(), tr("Name"), COLUMN_PEERNAME, tr("Search name")); ui.filterLineEdit->addFilter(QIcon(), tr("Peer ID"), COLUMN_PEERID, tr("Search peer ID")); ui.filterLineEdit->setCurrentFilter(COLUMN_PEERNAME); + connect(ui.filterLineEdit, SIGNAL(textChanged(QString)), PGPIdItemProxy, SLOT(setFilterWildcard(QString))); + } void NetworkDialog::changeEvent(QEvent *e) @@ -177,14 +159,16 @@ void NetworkDialog::changeEvent(QEvent *e) void NetworkDialog::connectTreeWidgetCostumPopupMenu( QPoint /*point*/ ) { - //std::cerr << "NetworkDialog::connectTreeWidgetCostumPopupMenu( QPoint point ) called" << std::endl; - QTreeWidgetItem *wi = getCurrentNeighbour(); - if (!wi) - return; + + QModelIndexList l = ui.connectTreeWidget->selectionModel()->selection().indexes(); + if(l.empty()) + { + return; + } QMenu *contextMnu = new QMenu; - RsPgpId peer_id(wi->text(COLUMN_PEERID).toStdString()) ; + RsPgpId peer_id(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), COLUMN_PEERID)).toString().toStdString()) ; // That's what context menus are made for RsPeerDetails detail; @@ -271,13 +255,17 @@ void NetworkDialog::removeUnusedKeys() } QMessageBox::warning(NULL,tr("Keyring info"),tr("Key removal has failed. Your keyring remains intact.\n\nReported error:")+" "+error_string ) ; } - insertConnect() ; + updateDisplay(); +// insertConnect() ; } void NetworkDialog::denyFriend() { - QTreeWidgetItem *wi = getCurrentNeighbour(); - RsPgpId peer_id( wi->text(COLUMN_PEERID).toStdString() ); + QModelIndexList l = ui.connectTreeWidget->selectionModel()->selection().indexes(); + if(l.empty()) + return; + + RsPgpId peer_id(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), COLUMN_PEERID)).toString().toStdString()); rsPeers->removeFriend(peer_id) ; securedUpdateDisplay(); @@ -300,27 +288,32 @@ void NetworkDialog::denyFriend() void NetworkDialog::makeFriend() { - PGPKeyDialog::showIt(RsPgpId(getCurrentNeighbour()->text(COLUMN_PEERID).toStdString()), PGPKeyDialog::PageDetails); + + QModelIndexList l = ui.connectTreeWidget->selectionModel()->selection().indexes(); + if(l.empty()) + return; + + PGPKeyDialog::showIt(RsPgpId(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), COLUMN_PEERID)).toString().toStdString()), PGPKeyDialog::PageDetails); } /** Shows Peer Information/Auth Dialog */ void NetworkDialog::peerdetails() { - QTreeWidgetItem* item = getCurrentNeighbour(); - if (item == NULL) { - return; - } - PGPKeyDialog::showIt(RsPgpId(item->text(COLUMN_PEERID).toStdString()), PGPKeyDialog::PageDetails); + QModelIndexList l = ui.connectTreeWidget->selectionModel()->selection().indexes(); + if(l.empty()) + return; + + PGPKeyDialog::showIt(RsPgpId(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), COLUMN_PEERID)).toString().toStdString()), PGPKeyDialog::PageDetails); } void NetworkDialog::copyLink() { - QTreeWidgetItem *wi = getCurrentNeighbour(); - if (wi == NULL) { - return; - } + QModelIndexList l = ui.connectTreeWidget->selectionModel()->selection().indexes(); + if(l.empty()) + return; - RsPgpId peer_id ( wi->text(COLUMN_PEERID).toStdString() ) ; + + RsPgpId peer_id (ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), COLUMN_PEERID)).toString().toStdString()) ; QList urls; RetroShareLink link = RetroShareLink::createPerson(peer_id); @@ -356,225 +349,14 @@ void NetworkDialog::copyLink() // /* window will destroy itself! */ //} -void NetworkDialog::updateDisplay() -{ - insertConnect() ; -} -/* get the list of Neighbours from the RsIface. */ -void NetworkDialog::insertConnect() -{ -// static time_t last_time = 0 ; - - if (!rsPeers) - return; - -// // Because this is called from a qt signal, there's no limitation between calls. - time_t now = time(NULL); - - std::list neighs; //these are GPG ids - std::list::iterator it; - rsPeers->getGPGAllList(neighs); - - /* get a link to the table */ - QTreeWidget *connectWidget = ui.connectTreeWidget; - /* disable sorting while editing the table */ - connectWidget->setSortingEnabled(false); - - //remove items - int index = 0; - while (index < connectWidget->topLevelItemCount()) - { - RsPgpId gpg_widget_id( (connectWidget->topLevelItem(index))->text(COLUMN_PEERID).toStdString() ); - RsPeerDetails detail; - if ( (!rsPeers->getGPGDetails(gpg_widget_id, detail)) || (ui.onlyTrustedKeys->isChecked() && (detail.validLvl < RS_TRUST_LVL_MARGINAL && !detail.accept_connection))) - delete (connectWidget->takeTopLevelItem(index)); - else - ++index; - } - - for(it = neighs.begin(); it != neighs.end(); ++it) - { -#ifdef NET_DEBUG - std::cerr << "NetworkDialog::insertConnect() inserting gpg key : " << *it << std::endl; -#endif - if (*it == rsPeers->getGPGOwnId()) { - continue; - } - - RsPeerDetails detail; - if (!rsPeers->getGPGDetails(*it, detail)) - { - continue; /* BAD */ - } - - /* make a widget per friend */ - QTreeWidgetItem *item; - QList list = connectWidget->findItems(QString::fromStdString( (*it).toStdString() ), Qt::MatchExactly, COLUMN_PEERID); - if (list.size() == 1) { - item = list.front(); - } else { - //create new item -#ifdef NET_DEBUG - std::cerr << "NetworkDialog::insertConnect() creating new tree widget item : " << *it << std::endl; -#endif - item = new RSTreeWidgetItem(compareNetworkRole, 0); - item -> setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); - - int S = QFontMetricsF(font()).height() ; - item -> setSizeHint(COLUMN_CHECK, QSize( S,S ) ); - - /* (1) Person */ - item -> setText(COLUMN_PEERNAME, QString::fromUtf8(detail.name.c_str())); - - /* (4) key id */ - item -> setText(COLUMN_PEERID, QString::fromStdString(detail.gpg_id.toStdString())); - } - - //QString TrustLevelString ; - - /* (2) Key validity */ - if (detail.ownsign) - { - item -> setText(COLUMN_I_AUTH_PEER, tr("Personal signature")); - item -> setToolTip(COLUMN_I_AUTH_PEER, tr("PGP key signed by you")); - } - else - switch(detail.trustLvl) - { - case RS_TRUST_LVL_MARGINAL: item->setText(COLUMN_I_AUTH_PEER,tr("Marginally trusted peer")) ; break; - case RS_TRUST_LVL_FULL: - case RS_TRUST_LVL_ULTIMATE: item->setText(COLUMN_I_AUTH_PEER,tr("Fully trusted peer")) ; break ; - case RS_TRUST_LVL_UNKNOWN: - case RS_TRUST_LVL_UNDEFINED: - case RS_TRUST_LVL_NEVER: - default: item->setText(2,tr("Untrusted peer")) ; break ; - } - - /* (3) has me auth */ - QString PeerAuthenticationString ; - - if (detail.hasSignedMe) - PeerAuthenticationString = tr("Yes"); - else - PeerAuthenticationString = tr("No"); - - item->setText(COLUMN_PEER_AUTH_ME,PeerAuthenticationString) ; - - uint64_t last_time_used = now - detail.lastUsed ; - QString lst_used_str ; - - if(last_time_used < 3600) - lst_used_str = tr("Last hour") ; - else if(last_time_used < 86400) - lst_used_str = tr("Today") ; - else if(last_time_used > 86400 * 15000) - lst_used_str = tr("Never"); - else - lst_used_str = tr("%1 days ago").arg((int)( last_time_used / 86400 )) ; - - QString lst_used_sort_str = QString::number(detail.lastUsed,'f',10); - - item->setText(COLUMN_LAST_USED,lst_used_str) ; - item->setData(COLUMN_LAST_USED,ROLE_SORT,lst_used_sort_str) ; - - /** - * Determinated the Background Color - */ - QColor backgrndcolor; - - if (detail.accept_connection) - { - item -> setText(COLUMN_CHECK, "0"); - item -> setIcon(COLUMN_CHECK,(QIcon(IMAGE_AUTHED))); - if (detail.ownsign) - { - backgrndcolor = backgroundColorOwnSign(); - } - else - { - backgrndcolor = backgroundColorAcceptConnection(); - } - } - else - { - item -> setText(COLUMN_CHECK, "1"); - - if (detail.hasSignedMe) - { - backgrndcolor = backgroundColorHasSignedMe(); - item -> setIcon(COLUMN_CHECK,(QIcon(IMAGE_DENIED))); - for(int k=0;k setToolTip(k, QString::fromUtf8(detail.name.c_str()) + tr(" has authenticated you. \nRight-click and select 'make friend' to be able to connect.")); - } - else - { - backgrndcolor = backgroundColorDenied(); - item -> setIcon(COLUMN_CHECK,(QIcon(IMAGE_DENIED))); - } - } - - // Color each Background column in the Network Tab except the first one => 1-9 - // whith the determinated color - for(int i = 0; i setBackground(i,QBrush(backgrndcolor)); - - if( (detail.accept_connection || detail.validLvl >= RS_TRUST_LVL_MARGINAL) || !ui.onlyTrustedKeys->isChecked()) - connectWidget->addTopLevelItem(item); - } - - // add self to network. - RsPeerDetails ownGPGDetails; - rsPeers->getGPGDetails(rsPeers->getGPGOwnId(), ownGPGDetails); - /* make a widget per friend */ - QTreeWidgetItem *self_item; - QList list = connectWidget->findItems(QString::fromStdString(ownGPGDetails.gpg_id.toStdString()), Qt::MatchExactly, COLUMN_PEERID); - if (list.size() == 1) { - self_item = list.front(); - } else { - self_item = new RSTreeWidgetItem(compareNetworkRole, 0); - self_item->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); - } - self_item -> setText(COLUMN_CHECK, "0"); - self_item->setIcon(COLUMN_CHECK,(QIcon(IMAGE_AUTHED))); - self_item->setText(COLUMN_PEERNAME, QString::fromUtf8(ownGPGDetails.name.c_str()) + " (" + tr("yourself") + ")"); - self_item->setText(COLUMN_I_AUTH_PEER,"N/A"); - self_item->setText(COLUMN_PEERID, QString::fromStdString(ownGPGDetails.gpg_id.toStdString())); - - // Color each Background column in the Network Tab except the first one => 1-9 - for(int i=0;isetBackground(i,backgroundColorSelf()) ; - } - connectWidget->addTopLevelItem(self_item); - - /* enable sorting */ - connectWidget->setSortingEnabled(true); - /* update display */ - connectWidget->update(); - - if (ui.filterLineEdit->text().isEmpty() == false) { - filterItems(ui.filterLineEdit->text()); - } - -} - -QTreeWidgetItem *NetworkDialog::getCurrentNeighbour() -{ - if (ui.connectTreeWidget->selectedItems().size() != 0) - { - return ui.connectTreeWidget -> currentItem(); - } - - return NULL; -} /* Utility Fns */ -RsPeerId getNeighRsCertId(QTreeWidgetItem *i) +/*RsPeerId getNeighRsCertId(QTreeWidgetItem *i) { RsPeerId id ( (i -> text(COLUMN_PEERID)).toStdString() ); return id; -} +} */ void NetworkDialog::on_actionAddFriend_activated() { // /* Create a new input dialog, which allows users to create files, too */ @@ -700,44 +482,23 @@ void NetworkDialog::on_actionCreate_New_Profile_activated() // Settings->endGroup(); // } -void NetworkDialog::filterColumnChanged(int) +void NetworkDialog::filterColumnChanged(int col) { - filterItems(ui.filterLineEdit->text()); + if(PGPIdItemProxy) + PGPIdItemProxy->setFilterKeyColumn(col); + //filterItems(ui.filterLineEdit->text()); } -void NetworkDialog::filterItems(const QString &text) -{ - int filterColumn = ui.filterLineEdit->currentFilter(); - int count = ui.connectTreeWidget->topLevelItemCount (); - for (int index = 0; index < count; ++index) { - filterItem(ui.connectTreeWidget->topLevelItem(index), text, filterColumn); - } + +void NetworkDialog::updateDisplay() +{ + if (!rsPeers) + return; + //update ids list + std::list new_neighs; + rsPeers->getGPGAllList(new_neighs); + //refresh model + PGPIdItemModel->data_updated(new_neighs); } -bool NetworkDialog::filterItem(QTreeWidgetItem *item, const QString &text, int filterColumn) -{ - bool visible = true; - - if (text.isEmpty() == false) { - if (item->text(filterColumn).contains(text, Qt::CaseInsensitive) == false) { - visible = false; - } - } - - int visibleChildCount = 0; - int count = item->childCount(); - for (int index = 0; index < count; ++index) { - if (filterItem(item->child(index), text, filterColumn)) { - ++visibleChildCount; - } - } - - if (visible || visibleChildCount) { - item->setHidden(false); - } else { - item->setHidden(true); - } - - return (visible || visibleChildCount); -} diff --git a/retroshare-gui/src/gui/NetworkDialog.h b/retroshare-gui/src/gui/NetworkDialog.h index 2d90e98e7..6f3851907 100644 --- a/retroshare-gui/src/gui/NetworkDialog.h +++ b/retroshare-gui/src/gui/NetworkDialog.h @@ -25,9 +25,15 @@ #include "ui_NetworkDialog.h" #include "RsAutoUpdatePage.h" +#include "gui/NetworkDialog/pgpid_item_model.h" +#include "gui/NetworkDialog/pgpid_item_proxy.h" + +//tmp +class QTreeWidgetItem; class RSTreeWidgetItemCompareRole ; + class NetworkDialog : public RsAutoUpdatePage { Q_OBJECT @@ -42,23 +48,22 @@ public: /** Default Constructor */ NetworkDialog(QWidget *parent = 0); - //void load(); virtual void updateDisplay() ; // overloaded from RsAutoUpdatePage - + QColor backgroundColorSelf() const { return mBackgroundColorSelf; } QColor backgroundColorOwnSign() const { return mBackgroundColorOwnSign; } QColor backgroundColorAcceptConnection() const { return mBackgroundColorAcceptConnection; } QColor backgroundColorHasSignedMe() const { return mBackgroundColorHasSignedMe; } QColor backgroundColorDenied() const { return mBackgroundColorDenied; } - void setBackgroundColorSelf(QColor color) { mBackgroundColorSelf = color; } - void setBackgroundColorOwnSign(QColor color) { mBackgroundColorOwnSign = color; } - void setBackgroundColorAcceptConnection(QColor color) { mBackgroundColorAcceptConnection = color; } - void setBackgroundColorHasSignedMe(QColor color) { mBackgroundColorHasSignedMe = color; } - void setBackgroundColorDenied(QColor color) { mBackgroundColorDenied = color; } + void setBackgroundColorSelf(QColor color) { PGPIdItemModel->setBackgroundColorSelf(color); mBackgroundColorSelf = color; } + void setBackgroundColorOwnSign(QColor color) { PGPIdItemModel->setBackgroundColorOwnSign(color); mBackgroundColorOwnSign = color; } + void setBackgroundColorAcceptConnection(QColor color) { PGPIdItemModel->setBackgroundColorAcceptConnection(color); mBackgroundColorAcceptConnection = color; } + void setBackgroundColorHasSignedMe(QColor color) { PGPIdItemModel->setBackgroundColorHasSignedMe(color); mBackgroundColorHasSignedMe = color; } + void setBackgroundColorDenied(QColor color) { PGPIdItemModel->setBackgroundColorDenied(color); mBackgroundColorDenied = color; } private: - void insertConnect(); +// void insertConnect(); // std::string loadneighbour(); /* void loadneighbour(); */ //void updateNewDiscoveryInfo() ; @@ -68,7 +73,7 @@ protected: private slots: - void removeUnusedKeys() ; + void removeUnusedKeys() ; void makeFriend() ; void denyFriend() ; // void deleteCert() ; @@ -104,14 +109,15 @@ private slots: // void on_actionTabsTriangular_activated(); void filterColumnChanged(int); - void filterItems(const QString &text); +// void filterItems(const QString &text); + + private: - QTreeWidgetItem *getCurrentNeighbour(); // class NetworkView *networkview; - bool filterItem(QTreeWidgetItem *item, const QString &text, int filterColumn); +// bool filterItem(QTreeWidgetItem *item, const QString &text, int filterColumn); /* Color definitions (for standard see qss.default) */ QColor mBackgroundColorSelf; @@ -122,6 +128,12 @@ private: RSTreeWidgetItemCompareRole *compareNetworkRole ; + //iinternal long lived data + std::list neighs; + + pgpid_item_model *PGPIdItemModel; + pgpid_item_proxy *PGPIdItemProxy; + /** Qt Designer generated object */ Ui::NetworkDialog ui; }; diff --git a/retroshare-gui/src/gui/NetworkDialog.ui b/retroshare-gui/src/gui/NetworkDialog.ui index 3c0fb4c93..833fb542b 100644 --- a/retroshare-gui/src/gui/NetworkDialog.ui +++ b/retroshare-gui/src/gui/NetworkDialog.ui @@ -41,7 +41,7 @@ Qt::Vertical - + 0 @@ -66,63 +66,6 @@ 16 - - true - - - true - - - true - - - true - - - true - - - true - - - 200 - - - true - - - - - - - - - Profile - - - - - Did I authenticated peer - - - Did I sign his PGP key - - - - - Has signed my key - - - - - Cert Id - - - - - Last used - -
diff --git a/retroshare-gui/src/gui/NetworkDialog/pgpid_item_model.cpp b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_model.cpp new file mode 100644 index 000000000..a4599414d --- /dev/null +++ b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_model.cpp @@ -0,0 +1,348 @@ +#include "pgpid_item_model.h" +#include +#include +#include +#include + + +/*TODO: + * using list here for internal data storage is not best option +*/ +pgpid_item_model::pgpid_item_model(std::list &neighs_, float &_font_height, QObject *parent) + : QAbstractTableModel(parent), neighs(neighs_), font_height(_font_height) +{ +} + +QVariant pgpid_item_model::headerData(int section, Qt::Orientation orientation, int role) const +{ + if(orientation == Qt::Horizontal) + { + if(role == Qt::ToolTipRole) + { + switch(section) + { + case COLUMN_CHECK: + return QString(tr(" Do you accept connections signed by this profile?")); + break; + case COLUMN_PEERNAME: + return QString(tr("Name of the profile")); + break; + case COLUMN_I_AUTH_PEER: + return QString(tr("This column indicates trust level and whether you signed the profile PGP key")); + break; + case COLUMN_PEER_AUTH_ME: + return QString(tr("Did that peer sign your own profile PGP key")); + break; + case COLUMN_PEERID: + return QString(tr("PGP Key Id of that profile")); + break; + case COLUMN_LAST_USED: + return QString(tr("Last time this key was used (received time, or to check connection)")); + break; + } + } + else if(role == Qt::DisplayRole) + { + switch(section) + { + case COLUMN_CHECK: + return QString(tr("Connections")); + break; + case COLUMN_PEERNAME: + return QString(tr("Profile")); + break; + case COLUMN_I_AUTH_PEER: + return QString(tr("Trust level")); + break; + case COLUMN_PEER_AUTH_ME: + return QString(tr("Has signed your key?")); + break; + case COLUMN_PEERID: + return QString(tr("Id")); + break; + case COLUMN_LAST_USED: + return QString(tr("Last used")); + break; + } + } + else if (role == Qt::TextAlignmentRole) + { + switch(section) + { + default: + return (uint32_t)(Qt::AlignHCenter | Qt::AlignVCenter); + break; + } + } + else if(role == Qt::SizeHintRole) + { + switch(section) + { + case COLUMN_CHECK: + return 25*font_height; + break; + case COLUMN_PEERNAME: case COLUMN_I_AUTH_PEER: case COLUMN_PEER_AUTH_ME: + return 200*font_height; + break; + case COLUMN_LAST_USED: + return 75*font_height; + break; + } + + } + } + return QVariant(); +} + + +int pgpid_item_model::rowCount(const QModelIndex &/*parent*/) const +{ + return neighs.size(); +} + +int pgpid_item_model::columnCount(const QModelIndex &/*parent*/) const +{ + return COLUMN_COUNT; +} + + +QVariant pgpid_item_model::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if((unsigned)index.row() >= neighs.size()) + return QVariant(); + + + //shit code (please rewrite it) + + std::list::iterator it = neighs.begin(); + for(int i = 0; i < index.row(); i++) + it++; + RsPeerDetails detail; + if (!rsPeers->getGPGDetails(*it, detail)) + return QVariant(); + //shit code end + if(role == Qt::EditRole) //some columns return raw data for editrole, used for proper filtering + { + switch(index.column()) + { + case COLUMN_LAST_USED: + return detail.lastUsed; + break; + case COLUMN_I_AUTH_PEER: + { + if (detail.ownsign) + return RS_TRUST_LVL_ULTIMATE; + return detail.trustLvl; + } + break; + case COLUMN_PEER_AUTH_ME: + return detail.hasSignedMe; + break; + case COLUMN_CHECK: + return detail.accept_connection; + break; + default: + break; + } + + } + //we using editrole only where it is useful, for other data we use display, so no "else if" here + if(role == Qt::DisplayRole || role == Qt::EditRole) + { + switch(index.column()) + { + case COLUMN_PEERNAME: + return QString::fromUtf8(detail.name.c_str()); + break; + case COLUMN_PEERID: + return QString::fromStdString(detail.gpg_id.toStdString()); + break; + case COLUMN_I_AUTH_PEER: + { + if (detail.ownsign) + return tr("Personal signature"); + else + { + switch(detail.trustLvl) + { + case RS_TRUST_LVL_MARGINAL: return tr("Marginally trusted peer") ; break; + case RS_TRUST_LVL_FULL: + case RS_TRUST_LVL_ULTIMATE: return tr("Fully trusted peer") ; break ; + case RS_TRUST_LVL_UNKNOWN: + case RS_TRUST_LVL_UNDEFINED: + case RS_TRUST_LVL_NEVER: + default: return tr("Untrusted peer") ; break ; + } + } + } + break; + case COLUMN_PEER_AUTH_ME: + { + if (detail.hasSignedMe) + return tr("Yes"); + else + return tr("No"); + } + break; + case COLUMN_LAST_USED: + { + time_t now = time(NULL); + uint64_t last_time_used = now - detail.lastUsed ; + QString lst_used_str ; + + if(last_time_used < 3600) + lst_used_str = tr("Last hour") ; + else if(last_time_used < 86400) + lst_used_str = tr("Today") ; + else if(last_time_used > 86400 * 15000) + lst_used_str = tr("Never"); + else + lst_used_str = tr("%1 days ago").arg((int)( last_time_used / 86400 )) ; + + + return lst_used_str; + } + break; + case COLUMN_CHECK: + { + if (detail.accept_connection) + { + return tr("Accepted"); + } + else + { + return tr(" - "); + } + } + break; + + + } + } + else if(role == Qt::ToolTipRole) + { + switch(index.column()) + { + case COLUMN_I_AUTH_PEER: + { + if (detail.ownsign) + return tr("PGP key signed by you"); + } + break; + default: + { + if (!detail.accept_connection && detail.hasSignedMe) + { + return QString::fromUtf8(detail.name.c_str()) + tr(" has authenticated you. \nRight-click and select 'make friend' to be able to connect."); + } + } + break; + + } + } + else if(role == Qt::DecorationRole) + { + switch(index.column()) + { + case COLUMN_CHECK: + { + if (detail.accept_connection) + return QIcon(IMAGE_AUTHED); + else + return QIcon(IMAGE_DENIED); + + } + break; + } + } + else if(role == Qt::BackgroundRole) + { + if (detail.accept_connection) + { + if (detail.ownsign) + { + return QBrush(mBackgroundColorOwnSign); + } + else + { + return QBrush(mBackgroundColorAcceptConnection); + } + } + else + { + if (detail.hasSignedMe) + { + return QBrush(mBackgroundColorHasSignedMe); + } + else + { + return QBrush(mBackgroundColorDenied); + } + } + } + return QVariant(); +} + + +//following code is just a poc, it's still suboptimal, unefficient, but much better then existing rs code + +void pgpid_item_model::data_updated(std::list &new_neighs) +{ + + //shit code follow (rewrite this please) + size_t old_size = neighs.size(), new_size = 0; + std::list old_neighs = neighs; + + new_size = new_neighs.size(); + //set model data to new cleaned up data + neighs = new_neighs; + neighs.sort(); + neighs.unique(); //remove possible dups + + //reflect actual row count in model + if(old_size < new_size) + { + beginInsertRows(QModelIndex(), old_size, new_size); + insertRows(old_size, new_size - old_size); + endInsertRows(); + } + else if(new_size < old_size) + { + beginRemoveRows(QModelIndex(), new_size, old_size); + removeRows(old_size, old_size - new_size); + endRemoveRows(); + } + //update data in ui, to avoid unnecessary redraw and ui updates, updating only changed elements + //TODO: libretroshare should implement a way to obtain only changed elements via some signalling non-blocking api. + { + size_t ii1 = 0; + for(auto i1 = neighs.begin(), end1 = neighs.end(), i2 = old_neighs.begin(), end2 = old_neighs.end(); i1 != end1; ++i1, ++i2, ii1++) + { + if(i2 == end2) + break; + if(*i1 != *i2) + { + QModelIndex topLeft = createIndex(ii1,0), bottomRight = createIndex(ii1, COLUMN_COUNT-1); + emit dataChanged(topLeft, bottomRight); + } + } + } + if(new_size > old_size) + { + QModelIndex topLeft = createIndex(old_size ? old_size -1 : 0 ,0), bottomRight = createIndex(new_size -1, COLUMN_COUNT-1); + emit dataChanged(topLeft, bottomRight); + } + //dirty solution for initial data fetch + //TODO: do it properly! + if(!old_size) + { + beginResetModel(); + endResetModel(); + } + + //shit code end +} + diff --git a/retroshare-gui/src/gui/NetworkDialog/pgpid_item_model.h b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_model.h new file mode 100644 index 000000000..f42ae5e83 --- /dev/null +++ b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_model.h @@ -0,0 +1,58 @@ +#ifndef KEY_ITEM_MODEL_H +#define KEY_ITEM_MODEL_H + +#include +#include +#include + +#define IMAGE_AUTHED ":/images/accepted16.png" +#define IMAGE_DENIED ":/images/denied16.png" +#define IMAGE_TRUSTED ":/images/rs-2.png" + + +#define COLUMN_CHECK 0 +#define COLUMN_PEERNAME 1 +#define COLUMN_I_AUTH_PEER 2 +#define COLUMN_PEER_AUTH_ME 3 +#define COLUMN_PEERID 4 +#define COLUMN_LAST_USED 5 +#define COLUMN_COUNT 6 + + +class pgpid_item_model : public QAbstractTableModel +{ + Q_OBJECT + +public: + explicit pgpid_item_model(std::list &neighs, float &font_height, QObject *parent = nullptr); + + // Header: + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const ; + + + int rowCount(const QModelIndex &parent = QModelIndex()) const ; + int columnCount(const QModelIndex &parent = QModelIndex()) const ; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const ; + + void setBackgroundColorSelf(QColor color) { mBackgroundColorSelf = color; } + void setBackgroundColorOwnSign(QColor color) { mBackgroundColorOwnSign = color; } + void setBackgroundColorAcceptConnection(QColor color) { mBackgroundColorAcceptConnection = color; } + void setBackgroundColorHasSignedMe(QColor color) { mBackgroundColorHasSignedMe = color; } + void setBackgroundColorDenied(QColor color) { mBackgroundColorDenied = color; } + + +public slots: + void data_updated(std::list &new_neighs); + +private: + std::list &neighs; + float font_height; + QColor mBackgroundColorSelf; + QColor mBackgroundColorOwnSign; + QColor mBackgroundColorAcceptConnection; + QColor mBackgroundColorHasSignedMe; + QColor mBackgroundColorDenied; +}; + +#endif // KEY_ITEM_MODEL_H diff --git a/retroshare-gui/src/gui/NetworkDialog/pgpid_item_proxy.cpp b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_proxy.cpp new file mode 100644 index 000000000..6fb62dd78 --- /dev/null +++ b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_proxy.cpp @@ -0,0 +1,48 @@ +#include "pgpid_item_proxy.h" + +//TODO: include only required headers here +#include +#include +#include +#include + + +//TODO: set this defines in one place +// Defines for key list columns +#define COLUMN_CHECK 0 +#define COLUMN_PEERNAME 1 +#define COLUMN_I_AUTH_PEER 2 +#define COLUMN_PEER_AUTH_ME 3 +#define COLUMN_PEERID 4 +#define COLUMN_LAST_USED 5 +#define COLUMN_COUNT 6 + + + +pgpid_item_proxy::pgpid_item_proxy(QObject *parent) : + QSortFilterProxyModel(parent) +{ + +} + +void pgpid_item_proxy::use_only_trusted_keys(bool val) +{ + only_trusted_keys = val; + filterChanged(); +} + +bool pgpid_item_proxy::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const +{ + if(only_trusted_keys) + { + if(!rsPeers) + return false; + RsPgpId peer_id (sourceModel()->data(sourceModel()->index(sourceRow, COLUMN_PEERID, sourceParent)).toString().toStdString()); + RsPeerDetails details; + if(!rsPeers->getGPGDetails(peer_id, details)) + return false; + if(details.validLvl < RS_TRUST_LVL_MARGINAL) + return false; + } + return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent); +} diff --git a/retroshare-gui/src/gui/NetworkDialog/pgpid_item_proxy.h b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_proxy.h new file mode 100644 index 000000000..e67eeeee8 --- /dev/null +++ b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_proxy.h @@ -0,0 +1,21 @@ +#ifndef PGPID_ITEM_PROXY_H +#define PGPID_ITEM_PROXY_H + +#include + +class pgpid_item_proxy : + public QSortFilterProxyModel +{ + Q_OBJECT + +public: + pgpid_item_proxy(QObject *parent = nullptr); + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; +public slots: + void use_only_trusted_keys(bool val); + +private: + bool only_trusted_keys = false; +}; + +#endif // PGPID_ITEM_PROXY_H diff --git a/retroshare-gui/src/gui/RemoteDirModel.cpp b/retroshare-gui/src/gui/RemoteDirModel.cpp index 7ffbcf5bd..556657d13 100644 --- a/retroshare-gui/src/gui/RemoteDirModel.cpp +++ b/retroshare-gui/src/gui/RemoteDirModel.cpp @@ -1065,10 +1065,21 @@ void RetroshareDirModel::createCollectionFile(QWidget *parent, const QModelIndex std::vector dirVec; getDirDetailsFromSelect(list, dirVec); - RsCollection(dirVec).openNewColl(parent); + FileSearchFlags f = RemoteMode?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL ; + + QString dir_name; + if(!RemoteMode) + { + if(dirVec.size()) + { + const DirDetails& details = dirVec[0]; + dir_name = QDir(QString::fromUtf8(details.name.c_str())).dirName(); + } + } + RsCollection(dirVec,f).openNewColl(parent,dir_name); } -void RetroshareDirModel::downloadSelected(const QModelIndexList &list) +void RetroshareDirModel::downloadSelected(const QModelIndexList &list,bool interactive) { if (!RemoteMode) { @@ -1085,35 +1096,38 @@ void RetroshareDirModel::downloadSelected(const QModelIndexList &list) std::vector dirVec; getDirDetailsFromSelect(list, dirVec); + FileSearchFlags f = RemoteMode?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL ; - /* Fire off requests */ - for (int i = 0, n = dirVec.size(); i < n; ++i) - { - if (!RemoteMode) - { - continue; /* don't try to download local stuff */ - } + if(interactive) + RsCollection(dirVec,f).downloadFiles() ; + else /* Fire off requests */ + for (int i = 0, n = dirVec.size(); i < n; ++i) + { + if (!RemoteMode) + { + continue; /* don't try to download local stuff */ + } - const DirDetails& details = dirVec[i]; + const DirDetails& details = dirVec[i]; - /* if it is a file */ - if (details.type == DIR_TYPE_FILE) - { - std::cerr << "RetroshareDirModel::downloadSelected() Calling File Request"; - std::cerr << std::endl; - std::list srcIds; - srcIds.push_back(details.id); - rsFiles -> FileRequest(details.name, details.hash, - details.count, "", RS_FILE_REQ_ANONYMOUS_ROUTING, srcIds); - } - /* if it is a dir, copy all files included*/ - else if (details.type == DIR_TYPE_DIR) - { - int prefixLen = details.path.rfind(details.name); - if (prefixLen < 0) continue; - downloadDirectory(details, prefixLen); - } - } + /* if it is a file */ + if (details.type == DIR_TYPE_FILE) + { + std::cerr << "RetroshareDirModel::downloadSelected() Calling File Request"; + std::cerr << std::endl; + std::list srcIds; + srcIds.push_back(details.id); + rsFiles -> FileRequest(details.name, details.hash, + details.count, "", RS_FILE_REQ_ANONYMOUS_ROUTING, srcIds); + } + /* if it is a dir, copy all files included*/ + else if (details.type == DIR_TYPE_DIR) + { + int prefixLen = details.path.rfind(details.name); + if (prefixLen < 0) continue; + downloadDirectory(details, prefixLen); + } + } } /* recursively download a directory */ diff --git a/retroshare-gui/src/gui/RemoteDirModel.h b/retroshare-gui/src/gui/RemoteDirModel.h index 73642dda4..ed394b795 100644 --- a/retroshare-gui/src/gui/RemoteDirModel.h +++ b/retroshare-gui/src/gui/RemoteDirModel.h @@ -63,7 +63,7 @@ class RetroshareDirModel : public QAbstractItemModel bool visible() { return _visible ;} /* Callback from GUI */ - void downloadSelected(const QModelIndexList &list); + void downloadSelected(const QModelIndexList &list, bool interactive); void createCollectionFile(QWidget *parent, const QModelIndexList &list); void getDirDetailsFromSelect (const QModelIndexList &list, std::vector & dirVec); diff --git a/retroshare-gui/src/gui/RetroShareLink.cpp b/retroshare-gui/src/gui/RetroShareLink.cpp index 3a0f7fb9a..d6bd38666 100644 --- a/retroshare-gui/src/gui/RetroShareLink.cpp +++ b/retroshare-gui/src/gui/RetroShareLink.cpp @@ -1220,6 +1220,11 @@ static void processList(const QStringList &list, const QString &textSingular, co errorList << &fileExist << &personExist << &personFailed << &personNotFound << &forumUnknown << &forumMsgUnknown << &channelUnknown << &channelMsgUnknown << &postedUnknown << &postedMsgUnknown << &messageReceipientNotAccepted << &messageReceipientUnknown; // not needed: forumFound, channelFound, messageStarted + // we want to merge all single file links into one collection + // if a collection tree link is found it is processed independen for the other file links + RsCollection col; + bool fileLinkFound = false; + for (linkIt = links.begin(); linkIt != links.end(); ++linkIt) { const RetroShareLink &link = *linkIt; @@ -1364,12 +1369,9 @@ static void processList(const QStringList &list, const QString &textSingular, co } break; - case TYPE_FILE: - { - RsCollection col ; - col.merge_in(link.name(),link.size(),RsFileHash(link.hash().toStdString())) ; - col.downloadFiles(); - } + case TYPE_FILE: + col.merge_in(link.name(),link.size(),RsFileHash(link.hash().toStdString())) ; + fileLinkFound = true; break; @@ -1557,6 +1559,10 @@ static void processList(const QStringList &list, const QString &textSingular, co } } + // were single file links found? + if (fileLinkFound) + col.downloadFiles(); + int countProcessed = 0; int countError = 0; diff --git a/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp b/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp index 2be092d7f..93028d20c 100644 --- a/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp +++ b/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp @@ -63,7 +63,9 @@ const static uint32_t timeToInactivity = 60 * 10; // in seconds /** Default constructor */ ChatLobbyDialog::ChatLobbyDialog(const ChatLobbyId& lid, QWidget *parent, Qt::WindowFlags flags) - : ChatDialog(parent, flags), lobbyId(lid) + : ChatDialog(parent, flags), lobbyId(lid), + bullet_red_128(":/icons/bullet_red_128.png"), bullet_grey_128(":/icons/bullet_grey_128.png"), + bullet_green_128(":/icons/bullet_green_128.png"), bullet_yellow_128(":/icons/bullet_yellow_128.png") { /* Invoke Qt Designer generated QObject setup routine */ ui.setupUi(this); @@ -556,16 +558,16 @@ void ChatLobbyDialog::updateParticipantsList() if(isParticipantMuted(it2->first)) - widgetitem->setIcon(COLUMN_ICON, QIcon(":/icons/bullet_red_128.png")); + widgetitem->setIcon(COLUMN_ICON, bullet_red_128); else if (tLastAct + timeToInactivity < now) - widgetitem->setIcon(COLUMN_ICON, QIcon(":/icons/bullet_grey_128.png")); + widgetitem->setIcon(COLUMN_ICON, bullet_grey_128); else - widgetitem->setIcon(COLUMN_ICON, QIcon(":/icons/bullet_green_128.png")); + widgetitem->setIcon(COLUMN_ICON, bullet_green_128); RsGxsId gxs_id; rsMsgs->getIdentityForChatLobby(lobbyId, gxs_id); - if (RsGxsId(participant.toStdString()) == gxs_id) widgetitem->setIcon(COLUMN_ICON, QIcon(":/icons/bullet_yellow_128.png")); + if (RsGxsId(participant.toStdString()) == gxs_id) widgetitem->setIcon(COLUMN_ICON, bullet_yellow_128); widgetitem->updateBannedState(); diff --git a/retroshare-gui/src/gui/chat/ChatLobbyDialog.h b/retroshare-gui/src/gui/chat/ChatLobbyDialog.h index 420524f93..dbe178678 100644 --- a/retroshare-gui/src/gui/chat/ChatLobbyDialog.h +++ b/retroshare-gui/src/gui/chat/ChatLobbyDialog.h @@ -120,6 +120,8 @@ private: QAction *showinpeopleAct; GxsIdChooser *ownIdChooser ; + //icons cache + QIcon bullet_red_128, bullet_grey_128, bullet_green_128, bullet_yellow_128; }; #endif diff --git a/retroshare-gui/src/gui/chat/ChatWidget.cpp b/retroshare-gui/src/gui/chat/ChatWidget.cpp index a8807cb3b..101214bab 100644 --- a/retroshare-gui/src/gui/chat/ChatWidget.cpp +++ b/retroshare-gui/src/gui/chat/ChatWidget.cpp @@ -1589,10 +1589,9 @@ void ChatWidget::fileHashingFinished(QList hashedFiles) RetroShareLink link; - if(mDefaultExtraFileFlags & RS_FILE_REQ_ANONYMOUS_ROUTING) - link = RetroShareLink::createFile(hashedFile.filename, hashedFile.size, QString::fromStdString(hashedFile.hash.toStdString())); - else - link = RetroShareLink::createExtraFile(hashedFile.filename, hashedFile.size, QString::fromStdString(hashedFile.hash.toStdString()),QString::fromStdString(rsPeers->getOwnId().toStdString())); + // We dont use extra links anymore, since files in the extra list can always be accessed using anonymous+encrypted FT. + + link = RetroShareLink::createFile(hashedFile.filename, hashedFile.size, QString::fromStdString(hashedFile.hash.toStdString())); if (hashedFile.flag & HashedFile::Picture) { message += QString("").arg(hashedFile.filepath); diff --git a/retroshare-gui/src/gui/common/RsCollection.cpp b/retroshare-gui/src/gui/common/RsCollection.cpp index f92598137..e22c9073d 100644 --- a/retroshare-gui/src/gui/common/RsCollection.cpp +++ b/retroshare-gui/src/gui/common/RsCollection.cpp @@ -56,14 +56,20 @@ RsCollection::RsCollection(const FileTree& fr) recursAddElements(_xml_doc,fr,0,_root) ; } -RsCollection::RsCollection(const std::vector& file_infos, QObject *parent) +RsCollection::RsCollection(const std::vector& file_infos,FileSearchFlags flags, QObject *parent) : QObject(parent), _xml_doc("RsCollection") { _root = _xml_doc.createElement("RsCollection"); _xml_doc.appendChild(_root); + if(! ( (flags & RS_FILE_HINTS_LOCAL) || (flags & RS_FILE_HINTS_REMOTE))) + { + std::cerr << "(EE) Wrong flags passed to RsCollection constructor. Please fix the code!" << std::endl; + return ; + } + for(uint32_t i = 0;iRequestDirDetails(details.children[i].ref, subDirDetails, flags)) continue; - recursAddElements(doc,subDirDetails,d) ; + recursAddElements(doc,subDirDetails,d,flags) ; } e.appendChild(d) ; @@ -408,9 +413,8 @@ bool RsCollection::save(QWidget *parent) const } -bool RsCollection::openNewColl(QWidget *parent) +bool RsCollection::openNewColl(QWidget *parent, QString fileName) { - QString fileName; if(!misc::getSaveFileName(parent, RshareSettings::LASTDIR_EXTRAFILE , QApplication::translate("RsCollectionFile", "Create collection file") , QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")" diff --git a/retroshare-gui/src/gui/common/RsCollection.h b/retroshare-gui/src/gui/common/RsCollection.h index 0a6e1e65f..87f536033 100644 --- a/retroshare-gui/src/gui/common/RsCollection.h +++ b/retroshare-gui/src/gui/common/RsCollection.h @@ -64,7 +64,7 @@ public: RsCollection(QObject *parent = 0) ; // create from list of files and directories - RsCollection(const std::vector& file_entries, QObject *parent = 0) ; + RsCollection(const std::vector& file_entries, FileSearchFlags flags, QObject *parent = 0) ; RsCollection(const FileTree& fr); virtual ~RsCollection() ; @@ -82,7 +82,7 @@ public: bool save(const QString& fileName) const ; // Open new collection - bool openNewColl(QWidget *parent); + bool openNewColl(QWidget *parent, QString fileName = ""); // Open existing collection bool openColl(const QString& fileName, bool readOnly = false, bool showError = true); @@ -98,7 +98,7 @@ private slots: private: - void recursAddElements(QDomDocument&,const DirDetails&,QDomElement&) const ; + void recursAddElements(QDomDocument&, const DirDetails&, QDomElement&, FileSearchFlags flags) const ; void recursAddElements(QDomDocument&,const ColFileInfo&,QDomElement&) const; void recursAddElements(QDomDocument& doc,const FileTree& ft,uint32_t index,QDomElement& e) const; diff --git a/retroshare-gui/src/gui/emojione/emotes.acs b/retroshare-gui/src/gui/emojione/emotes.acs index 7db8ef8f6..850c2b365 100644 --- a/retroshare-gui/src/gui/emojione/emotes.acs +++ b/retroshare-gui/src/gui/emojione/emotes.acs @@ -46,7 +46,7 @@ "emojione/people.png"|":neutral_face:":"emojione/1F610.png"; "emojione/people.png"|":expressionless:|-_-":"emojione/1F611.png"; "emojione/people.png"|":hushed:":"emojione/1F62F.png"; -"emojione/people.png"|":frowning:":"emojione/1f626.png"; +"emojione/people.png"|":frowning:":"emojione/1F626.png"; "emojione/people.png"|":anguished:":"emojione/1F627.png"; "emojione/people.png"|":open_mouth:|:-O|:O":"emojione/1F62E.png"; "emojione/people.png"|":astonished:":"emojione/1F632.png"; @@ -82,7 +82,7 @@ "emojione/people.png"|":alien:":"emojione/1F47D.png"; "emojione/people.png"|":space_invader:":"emojione/1F47E.png"; "emojione/people.png"|":robot_face:":"emojione/1f916.png"; -"emojione/people.png"|":jack_o_lantern:":"emojione/1f383.png"; +"emojione/people.png"|":jack_o_lantern:":"emojione/1F383.png"; "emojione/people.png"|":poop:|:shit:|:hankey:|:poo:":"emojione/1F4A9.png"; "emojione/people.png"|":smile_cat:|(@)":"emojione/1F638.png"; "emojione/people.png"|":joy_cat:":"emojione/1F639.png"; diff --git a/retroshare-gui/src/gui/gxs/GxsCommentDialog.ui b/retroshare-gui/src/gui/gxs/GxsCommentDialog.ui index 8b91fc8ca..7961136c0 100644 --- a/retroshare-gui/src/gui/gxs/GxsCommentDialog.ui +++ b/retroshare-gui/src/gui/gxs/GxsCommentDialog.ui @@ -13,7 +13,7 @@ Form - + @@ -22,7 +22,7 @@ 0 - + 9 @@ -36,7 +36,7 @@ - + @@ -80,7 +80,7 @@ - + Qt::Horizontal @@ -93,7 +93,7 @@ - + Voter ID: diff --git a/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.cpp b/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.cpp index 1a20c13e5..23a5327ed 100644 --- a/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.cpp +++ b/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.cpp @@ -21,13 +21,14 @@ * */ -#include -#include #include #include +#include #include #include +#include #include +#include #include "gui/common/RSElidedItemDelegate.h" #include "gui/gxs/GxsCommentTreeWidget.h" @@ -54,7 +55,8 @@ #define POST_COLOR_ROLE (Qt::UserRole+2) /* Images for context menu icons */ -#define IMAGE_MESSAGE ":/images/folder-draft.png" +#define IMAGE_MESSAGE ":/images/folder-draft.png" +#define IMAGE_COPY ":/images/copy.png" #define IMAGE_VOTEUP ":/images/vote_up.png" #define IMAGE_VOTEDOWN ":/images/vote_down.png" @@ -170,6 +172,7 @@ void GxsCommentTreeWidget::setCurrentCommentMsgId(QTreeWidgetItem *current, QTre if(current) { mCurrentCommentMsgId = RsGxsMessageId(current->text(PCITEM_COLUMN_MSGID).toStdString()); + mCurrentCommentText = current->text(PCITEM_COLUMN_COMMENT); } } @@ -180,6 +183,8 @@ void GxsCommentTreeWidget::customPopUpMenu(const QPoint& /*point*/) action->setDisabled(mCurrentCommentMsgId.isNull()); action = contextMnu.addAction(QIcon(IMAGE_MESSAGE), tr("Submit Comment"), this, SLOT(makeComment())); action->setDisabled(mMsgVersions.empty()); + action = contextMnu.addAction(QIcon(IMAGE_COPY), tr("Copy Comment"), this, SLOT(copyComment())); + action->setDisabled(mCurrentCommentMsgId.isNull()); contextMnu.addSeparator(); @@ -308,6 +313,14 @@ void GxsCommentTreeWidget::replyToComment() pcc.exec(); } +void GxsCommentTreeWidget::copyComment() +{ + QMimeData *mimeData = new QMimeData(); + mimeData->setHtml(""+mCurrentCommentText+""); + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setMimeData(mimeData, QClipboard::Clipboard); +} + void GxsCommentTreeWidget::setup(RsTokenService *token_service, RsGxsCommentService *comment_service) { mRsTokenService = token_service; diff --git a/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.h b/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.h index dcc2db991..e0cedc2f4 100644 --- a/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.h +++ b/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.h @@ -71,6 +71,8 @@ public slots: void makeComment(); void replyToComment(); + void copyComment(); + void voteUp(); void voteDown(); @@ -89,6 +91,7 @@ protected: std::set mMsgVersions; RsGxsMessageId mLatestMsgId; RsGxsMessageId mCurrentCommentMsgId; + QString mCurrentCommentText; RsGxsId mVoterId; std::map mLoadingMap; diff --git a/retroshare-gui/src/gui/gxschannels/CreateGxsChannelMsg.cpp b/retroshare-gui/src/gui/gxschannels/CreateGxsChannelMsg.cpp index e8b15ed8e..cc93d5627 100644 --- a/retroshare-gui/src/gui/gxschannels/CreateGxsChannelMsg.cpp +++ b/retroshare-gui/src/gui/gxschannels/CreateGxsChannelMsg.cpp @@ -630,7 +630,7 @@ void CreateGxsChannelMsg::sendMsg() std::string subject = std::string(misc::removeNewLine(subjectEdit->text()).toUtf8()); QString text; RsHtml::optimizeHtml(msgEdit, text); - std::string msg = text.toStdString(); + std::string msg = std::string(text.toUtf8()); std::list files; diff --git a/retroshare-gui/src/gui/msgs/MessageWidget.cpp b/retroshare-gui/src/gui/msgs/MessageWidget.cpp index fa3ecf5c0..2f00bcded 100644 --- a/retroshare-gui/src/gui/msgs/MessageWidget.cpp +++ b/retroshare-gui/src/gui/msgs/MessageWidget.cpp @@ -122,7 +122,7 @@ MessageWidget *MessageWidget::openMsg(const std::string &msgId, bool window) /** Constructor */ MessageWidget::MessageWidget(bool controlled, QWidget *parent, Qt::WindowFlags flags) -: QWidget(parent, flags) + : QWidget(parent, flags), toolButtonReply(NULL) { /* Invoke the Qt Designer generated object setup routine */ ui.setupUi(this); @@ -196,6 +196,7 @@ void MessageWidget::connectAction(enumActionType actionType, QToolButton* button break; case ACTION_REPLY: connect(button, SIGNAL(clicked()), this, SLOT(reply())); + toolButtonReply = button; break; case ACTION_REPLY_ALL: connect(button, SIGNAL(clicked()), this, SLOT(replyAll())); @@ -600,9 +601,11 @@ void MessageWidget::fill(const std::string &msgId) if ((msgInfo.msgflags & RS_MSG_SYSTEM) && msgInfo.rspeerid_srcId == ownId) { ui.fromText->setText("RetroShare"); + if (toolButtonReply) toolButtonReply->setEnabled(false); } else { ui.fromText->setText(link.toHtml()); ui.fromText->setToolTip(tooltip_string) ; + if (toolButtonReply) toolButtonReply->setEnabled(true); } ui.subjectText->setText(QString::fromUtf8(msgInfo.title.c_str())); diff --git a/retroshare-gui/src/gui/msgs/MessageWidget.h b/retroshare-gui/src/gui/msgs/MessageWidget.h index e4d26068b..b7255143f 100644 --- a/retroshare-gui/src/gui/msgs/MessageWidget.h +++ b/retroshare-gui/src/gui/msgs/MessageWidget.h @@ -95,6 +95,8 @@ private: QList tagLabels; + QToolButton* toolButtonReply; + /** Qt Designer generated object */ Ui::MessageWidget ui; }; diff --git a/retroshare-gui/src/gui/msgs/MessageWidget.ui b/retroshare-gui/src/gui/msgs/MessageWidget.ui index 1f59bdcd0..3ec22c157 100644 --- a/retroshare-gui/src/gui/msgs/MessageWidget.ui +++ b/retroshare-gui/src/gui/msgs/MessageWidget.ui @@ -209,6 +209,12 @@ + + + 0 + 0 + + 16777215 @@ -238,6 +244,12 @@ + + + 0 + 0 + + 16777215 diff --git a/retroshare-gui/src/gui/msgs/MessageWindow.cpp b/retroshare-gui/src/gui/msgs/MessageWindow.cpp index 9ad274b1e..a4ff106e6 100644 --- a/retroshare-gui/src/gui/msgs/MessageWindow.cpp +++ b/retroshare-gui/src/gui/msgs/MessageWindow.cpp @@ -68,7 +68,7 @@ MessageWindow::MessageWindow(QWidget *parent, Qt::WindowFlags flags) QMenu *printmenu = new QMenu(); printmenu->addAction(ui.actionPrint); printmenu->addAction(ui.actionPrint_Preview); - ui.printbutton->setMenu(printmenu); + ui.printButton->setMenu(printmenu); // create view menu QMenu *viewmenu = new QMenu(); @@ -120,7 +120,7 @@ void MessageWindow::addWidget(MessageWidget *widget) msgWidget->connectAction(MessageWidget::ACTION_REPLY, ui.replymessageButton); msgWidget->connectAction(MessageWidget::ACTION_REPLY_ALL, ui.replyallmessageButton); msgWidget->connectAction(MessageWidget::ACTION_FORWARD, ui.forwardmessageButton); - msgWidget->connectAction(MessageWidget::ACTION_PRINT, ui.printbutton); + msgWidget->connectAction(MessageWidget::ACTION_PRINT, ui.printButton); msgWidget->connectAction(MessageWidget::ACTION_PRINT, ui.actionPrint); msgWidget->connectAction(MessageWidget::ACTION_PRINT, actionPrint); msgWidget->connectAction(MessageWidget::ACTION_PRINT_PREVIEW, ui.actionPrint_Preview); @@ -216,7 +216,7 @@ void MessageWindow::setToolbarButtonStyle(Qt::ToolButtonStyle style) ui.replyallmessageButton->setToolButtonStyle(style); ui.forwardmessageButton->setToolButtonStyle(style); ui.tagButton->setToolButtonStyle(style); - ui.printbutton->setToolButtonStyle(style); + ui.printButton->setToolButtonStyle(style); ui.viewtoolButton->setToolButtonStyle(style); } diff --git a/retroshare-gui/src/gui/msgs/MessageWindow.ui b/retroshare-gui/src/gui/msgs/MessageWindow.ui index 445fd4c9d..7c5689dd7 100644 --- a/retroshare-gui/src/gui/msgs/MessageWindow.ui +++ b/retroshare-gui/src/gui/msgs/MessageWindow.ui @@ -11,11 +11,20 @@ - - + + 0 - + + 0 + + + 0 + + + 0 + + 0 @@ -44,8 +53,17 @@ QFrame::Sunken - - + + + 2 + + + 2 + + + 2 + + 2 @@ -81,7 +99,7 @@ - + Qt::Vertical @@ -187,7 +205,7 @@ - + Qt::Vertical @@ -223,7 +241,7 @@ - + Qt::NoFocus @@ -281,7 +299,7 @@ - + Qt::Horizontal diff --git a/retroshare-gui/src/gui/settings/ServerPage.cpp b/retroshare-gui/src/gui/settings/ServerPage.cpp index 9076d76af..62ef905a0 100755 --- a/retroshare-gui/src/gui/settings/ServerPage.cpp +++ b/retroshare-gui/src/gui/settings/ServerPage.cpp @@ -191,10 +191,11 @@ ServerPage::ServerPage(QWidget * parent, Qt::WindowFlags flags) connect(ui.extAddress, SIGNAL(textChanged(QString)),this,SLOT(saveAddresses())); connect(ui.dynDNS, SIGNAL(textChanged(QString)),this,SLOT(saveAddresses())); - connect(ui.hiddenpage_proxyAddress_tor, SIGNAL(textChanged(QString)),this,SLOT(saveAddresses())); - connect(ui.hiddenpage_proxyPort_tor, SIGNAL(valueChanged(int)),this,SLOT(saveAddresses())); - connect(ui.hiddenpage_proxyAddress_i2p, SIGNAL(textChanged(QString)),this,SLOT(saveAddresses())); - connect(ui.hiddenpage_proxyPort_i2p, SIGNAL(valueChanged(int)),this,SLOT(saveAddresses())); + connect(ui.tabWidget, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int))); + connect(ui.hiddenpage_proxyAddress_tor, SIGNAL(editingFinished()),this,SLOT(saveAddresses())); + connect(ui.hiddenpage_proxyPort_tor, SIGNAL(editingFinished()),this,SLOT(saveAddresses())); + connect(ui.hiddenpage_proxyAddress_i2p, SIGNAL(editingFinished()),this,SLOT(saveAddresses())); + connect(ui.hiddenpage_proxyPort_i2p, SIGNAL(editingFinished()),this,SLOT(saveAddresses())); connect(ui.totalDownloadRate,SIGNAL(valueChanged(int)),this,SLOT(saveRates())); connect(ui.totalUploadRate, SIGNAL(valueChanged(int)),this,SLOT(saveRates())); @@ -422,7 +423,6 @@ void ServerPage::load() whileBlocking(ui.hiddenpage_proxyAddress_i2p) -> setText(QString::fromStdString(proxyaddr)); whileBlocking(ui.hiddenpage_proxyPort_i2p) -> setValue(proxyport); - updateOutProxyIndicator(); } //Relay Tab @@ -873,8 +873,6 @@ void ServerPage::updateStatus() else ui.iconlabel_ext->setPixmap(QPixmap(":/images/ledoff1.png")); - // check for Tor - updateOutProxyIndicator(); } void ServerPage::toggleUPnP() @@ -910,6 +908,9 @@ void ServerPage::saveAddresses() saveCommon(); + if(ui.tabWidget->currentIndex() == 2) // hidden services tab + updateOutProxyIndicator(); + if (mIsHiddenNode) { saveAddressesHiddenNode(); return; @@ -991,6 +992,12 @@ void ServerPage::saveRates() rsConfig->SetMaxDataRates( ui.totalDownloadRate->value(), ui.totalUploadRate->value() ); } +void ServerPage::tabChanged(int page) +{ + if(page == 2) + updateOutProxyIndicator(); +} + /***********************************************************************************/ /***********************************************************************************/ /******* ALTERNATIVE VERSION IF HIDDEN NODE ***************************************/ @@ -1131,8 +1138,6 @@ void ServerPage::loadHiddenNode() whileBlocking(ui.hiddenpage_proxyAddress_i2p) -> setText(QString::fromStdString(proxyaddr)); whileBlocking(ui.hiddenpage_proxyPort_i2p) -> setValue(proxyport); - updateOutProxyIndicator(); - QString expected = ""; switch (mHiddenType) { case RS_HIDDEN_TYPE_I2P: @@ -1220,8 +1225,6 @@ void ServerPage::updateStatusHiddenNode() ui.iconlabel_ext->setPixmap(QPixmap(":/images/ledoff1.png")); #endif - - updateOutProxyIndicator(); } void ServerPage::saveAddressesHiddenNode() @@ -1554,8 +1557,6 @@ void ServerPage::loadCommon() whileBlocking(ui.hiddenpage_proxyPort_i2p) -> setValue(proxyport); whileBlocking(ui.hiddenpage_proxyPort_i2p_2)->setValue(proxyport); // this one is for bob tab - updateOutProxyIndicator(); - // don't use whileBlocking here ui.cb_enableBob->setChecked(mBobSettings.enableBob); diff --git a/retroshare-gui/src/gui/settings/ServerPage.h b/retroshare-gui/src/gui/settings/ServerPage.h index ce0e4baa4..e993d67e7 100755 --- a/retroshare-gui/src/gui/settings/ServerPage.h +++ b/retroshare-gui/src/gui/settings/ServerPage.h @@ -84,6 +84,7 @@ private slots: void ipWhiteListContextMenu(const QPoint &point); void removeBannedIp(); + void tabChanged(int page); // server void saveAddresses(); void saveRates(); diff --git a/retroshare-gui/src/gui/statistics/TurtleRouterDialog.cpp b/retroshare-gui/src/gui/statistics/TurtleRouterDialog.cpp index 8f35f6d57..ebb03eda2 100644 --- a/retroshare-gui/src/gui/statistics/TurtleRouterDialog.cpp +++ b/retroshare-gui/src/gui/statistics/TurtleRouterDialog.cpp @@ -5,6 +5,7 @@ #include "TurtleRouterDialog.h" #include #include +#include // for sort #include "gui/settings/rsharesettings.h" @@ -70,6 +71,10 @@ void TurtleRouterDialog::processSettings(bool bLoad) } +bool sr_Compare( TurtleRequestDisplayInfo m1, TurtleRequestDisplayInfo m2) +{ + return m1.age < m2.age; +} void TurtleRouterDialog::updateDisplay() { @@ -79,7 +84,9 @@ void TurtleRouterDialog::updateDisplay() std::vector tunnel_reqs_info ; rsTurtle->getInfo(hashes_info,tunnels_info,search_reqs_info,tunnel_reqs_info) ; - + + std::sort(search_reqs_info.begin(),search_reqs_info.end(),sr_Compare) ; + updateTunnelRequests(hashes_info,tunnels_info,search_reqs_info,tunnel_reqs_info) ; } @@ -162,8 +169,8 @@ void TurtleRouterDialog::updateTunnelRequests( const std::vectorfriendsDialog,SLOT(updatePeerStatusString(const QString&,const QString&,bool))); QObject::connect(notify,SIGNAL(ownStatusMessageChanged()),w->friendsDialog,SLOT(loadmypersonalstatus())); - QObject::connect(notify,SIGNAL(logInfoChanged(const QString&)) ,w->friendsDialog->networkDialog,SLOT(setLogInfo(QString))) ; +// QObject::connect(notify,SIGNAL(logInfoChanged(const QString&)) ,w->friendsDialog->networkDialog,SLOT(setLogInfo(QString))) ; QObject::connect(notify,SIGNAL(discInfoChanged()) ,w->friendsDialog->networkView,SLOT(update()),Qt::QueuedConnection) ; QObject::connect(notify,SIGNAL(errorOccurred(int,int,const QString&)),w,SLOT(displayErrorMessage(int,int,const QString&))) ; diff --git a/retroshare-gui/src/qss/qdarkstyle.qss b/retroshare-gui/src/qss/qdarkstyle.qss index 224497a48..de4fed11f 100644 --- a/retroshare-gui/src/qss/qdarkstyle.qss +++ b/retroshare-gui/src/qss/qdarkstyle.qss @@ -44,7 +44,7 @@ QFrame#titleBarFrame, QFrame#toolBarFrame QToolTip { border: 1px solid #3A3939; - background-color: rgb(90, 102, 117);; + background-color: rgb(90, 102, 117); color: white; padding: 1px; opacity: 200; @@ -76,11 +76,11 @@ QWidget:item:selected ForumsDialog, GxsForumThreadWidget { - qproperty-textColorRead: gray; + qproperty-textColorRead: darkgray; qproperty-textColorUnread: white; - qproperty-textColorUnreadChildren: gray; + qproperty-textColorUnreadChildren: red; qproperty-textColorNotSubscribed: white; - qproperty-textColorMissing: red; + qproperty-textColorMissing: darkred; } QMenuBar @@ -330,7 +330,7 @@ QTextEdit QPlainTextEdit { - background-color: #201F1F;; + background-color: #201F1F; color: silver; border-radius: 3px; border: 1px solid #3A3939; @@ -830,6 +830,14 @@ QTreeView, QListView background-color: #201F1F; } +QTreeView::item { + background-color: #201F1F; +} + +QTreeView::item:!selected { + color: #C0C0C0; +} + QTreeView:branch:selected, QTreeView:branch:hover { background: url(qdarkstyle/transparent.png); @@ -867,14 +875,14 @@ QTreeView::branch:open:has-children:has-siblings:hover { image: url(qdarkstyle/branch_open-on.png); } -QListView::item:!selected:hover, QListView::item:!selected:hover, QTreeView::item:!selected:hover { +QListView::item:!selected:hover, QTableView::item:!selected:hover, QTreeView::item:!selected:hover { background: rgba(0, 0, 0, 0); outline: 0; - color: #FFFFFF + color: #FFFFFF; } -QListView::item:selected:hover, QListView::item:selected:hover, QTreeView::item:selected:hover { - background: #78879b;; +QListView::item:selected:hover, QTableView::item:selected:hover, QTreeView::item:selected:hover { + background: #78879b; color: #FFFFFF; } diff --git a/retroshare-gui/src/retroshare-gui.pro b/retroshare-gui/src/retroshare-gui.pro index 79003f845..6e12665dc 100644 --- a/retroshare-gui/src/retroshare-gui.pro +++ b/retroshare-gui/src/retroshare-gui.pro @@ -614,8 +614,9 @@ HEADERS += rshare.h \ gui/statistics/BWGraph.h \ util/RsSyntaxHighlighter.h \ util/imageutil.h \ + gui/NetworkDialog/pgpid_item_model.h \ + gui/NetworkDialog/pgpid_item_proxy.h \ gui/common/RsCollection.h - # gui/ForumsDialog.h \ # gui/forums/ForumDetails.h \ # gui/forums/EditForumDetails.h \ @@ -974,8 +975,9 @@ SOURCES += main.cpp \ gui/statistics/BWGraph.cpp \ util/RsSyntaxHighlighter.cpp \ util/imageutil.cpp \ + gui/NetworkDialog/pgpid_item_model.cpp \ + gui/NetworkDialog/pgpid_item_proxy.cpp \ gui/common/RsCollection.cpp - # gui/ForumsDialog.cpp \ # gui/forums/ForumDetails.cpp \ # gui/forums/EditForumDetails.cpp \ diff --git a/retroshare-gui/src/util/misc.cpp b/retroshare-gui/src/util/misc.cpp index 11b414b85..a43a3c0e4 100644 --- a/retroshare-gui/src/util/misc.cpp +++ b/retroshare-gui/src/util/misc.cpp @@ -363,7 +363,7 @@ bool misc::getSaveFileName(QWidget *parent, RshareSettings::enumLastDir type , QString &file, QString *selectedFilter , QFileDialog::Options options) { - QString lastDir = Settings->getLastDir(type); + QString lastDir = Settings->getLastDir(type) + "/" + file; file = QFileDialog::getSaveFileName(parent, caption, lastDir, filter, selectedFilter, QFileDialog::DontUseNativeDialog | options); diff --git a/retroshare.pri b/retroshare.pri index e2397e62b..4f94b4c21 100644 --- a/retroshare.pri +++ b/retroshare.pri @@ -93,7 +93,7 @@ CONFIG *= no_rs_async_chat rs_async_chat:CONFIG -= no_rs_async_chat # To select your MacOsX version append the following assignation to qmake -# command line "CONFIG+=rs_macos10.11" where 10.11(default for Travis_CI) depends your version +# command line "CONFIG+=rs_macos10.11" where 10.11 depends your version CONFIG *= rs_macos10.11 rs_macos10.8:CONFIG -= rs_macos10.11 rs_macos10.9:CONFIG -= rs_macos10.11 @@ -174,37 +174,39 @@ win32 { } } -rs_macos10.8 { - message(***retroshare.pri: Set Target and SDK to MacOS 10.8 ) - QMAKE_MACOSX_DEPLOYMENT_TARGET=10.8 - QMAKE_MAC_SDK = macosx10.8 -} - -rs_macos10.9 { - message(***retroshare.pri: Set Target and SDK to MacOS 10.9 ) - QMAKE_MACOSX_DEPLOYMENT_TARGET=10.9 - QMAKE_MAC_SDK = macosx10.9 -} - -rs_macos10.10 { - message(***retroshare.pri: Set Target and SDK to MacOS 10.10 ) - QMAKE_MACOSX_DEPLOYMENT_TARGET=10.10 - QMAKE_MAC_SDK = macosx10.10 -} - -rs_macos10.11 { - message(***retroshare.pri: Set Target and SDK to MacOS 10.11 ) - QMAKE_MACOSX_DEPLOYMENT_TARGET=10.11 - QMAKE_MAC_SDK = macosx10.11 -} - -rs_macos10.12 { - message(***retroshare.pri: Set Target and SDK to MacOS 10.12 ) - QMAKE_MACOSX_DEPLOYMENT_TARGET=10.12 - QMAKE_MAC_SDK = macosx10.12 -} - macx { + rs_macos10.8 { + message(***retroshare.pri: Set Target and SDK to MacOS 10.8 ) + QMAKE_MACOSX_DEPLOYMENT_TARGET=10.8 + QMAKE_MAC_SDK = macosx10.8 + } + + rs_macos10.9 { + message(***retroshare.pri: Set Target and SDK to MacOS 10.9 ) + QMAKE_MACOSX_DEPLOYMENT_TARGET=10.9 + QMAKE_MAC_SDK = macosx10.9 + } + + rs_macos10.10 { + message(***retroshare.pri: Set Target and SDK to MacOS 10.10 ) + QMAKE_MACOSX_DEPLOYMENT_TARGET=10.10 + QMAKE_MAC_SDK = macosx10.10 + } + + rs_macos10.11 { + message(***retroshare.pri: Set Target and SDK to MacOS 10.11 ) + QMAKE_MACOSX_DEPLOYMENT_TARGET=10.11 + QMAKE_MAC_SDK = macosx10.11 + } + + rs_macos10.12 { + message(***retroshare.pri: Set Target and SDK to MacOS 10.12 ) + QMAKE_MACOSX_DEPLOYMENT_TARGET=10.12 + QMAKE_MAC_SDK = macosx10.12 + QMAKE_CXXFLAGS += -Wno-nullability-completeness + QMAKE_CFLAGS += -Wno-nullability-completeness + } + message(***retroshare.pri:MacOSX) BIN_DIR += "/usr/bin" INC_DIR += "/usr/include" @@ -272,3 +274,44 @@ rs_async_chat { rs_chatserver { DEFINES *= RS_CHATSERVER } + +########################################################################################################################################################### +# +# V07_NON_BACKWARD_COMPATIBLE_CHANGE_001: +# +# What: Computes the node id by performing a sha256 hash of the certificate's PGP signature, instead of simply picking up the last 20 bytes of it. +# +# Why: There is no real risk in forging a certificate with the same ID as the authentication is performed over the PGP signature of the certificate +# which hashes the full SSL certificate (i.e. the full serialized CERT_INFO structure). However the possibility to +# create two certificates with the same IDs is a problem, as it can be used to cause disturbance in the software. +# +# Backward compat: connexions impossible with non patched peers older than Nov 2017, probably because the SSL id that is computed is not the same on both side, +# and in particular unpatched peers see a cerficate with ID different (because computed with the old method) than the ID that was +# submitted when making friends. +# +# Note: the advantage of basing the ID on the signature rather than the public key is not very clear, given that the signature is based on a hash +# of the public key (and the rest of the certificate info). +# +# V07_NON_BACKWARD_COMPATIBLE_CHANGE_002: +# +# What: Use RSA+SHA256 instead of RSA+SHA1 for PGP certificate signatures +# +# Why: Sha1 is likely to be prone to primary collisions anytime soon, so it is urgent to turn to a more secure solution. +# +# Backward compat: unpatched peers after Nov 2017 are able to verify signatures since openpgp-sdk already handle it. +# +# V07_NON_BACKWARD_COMPATIBLE_CHANGE_003: +# +# What: Do not hash PGP certificate twice when signing +# +# Why: hasing twice is not per se a security issue, but it makes it harder to change the settings for hashing. +# +# Backward compat: patched peers cannot connect to non patched peers older than Nov 2017. +########################################################################################################################################################### + +#CONFIG += rs_v07_changes +rs_v07_changes { + DEFINES += V07_NON_BACKWARD_COMPATIBLE_CHANGE_001 + DEFINES += V07_NON_BACKWARD_COMPATIBLE_CHANGE_002 + DEFINES += V07_NON_BACKWARD_COMPATIBLE_CHANGE_003 +}