Merge remote-tracking branch 'retro/master' into qml_app_avatar_picker

This commit is contained in:
Angela Mazzurco 2017-07-12 17:56:26 +02:00
commit 0494dd7516
102 changed files with 4608 additions and 1861 deletions

View File

@ -1,5 +1,265 @@
retroshare06 (0.6.2-1.XXXXXX~YYYYYY) YYYYYY; urgency=low
244e8a8 csoler Sat, 1 Jul 2017 15:29:48 +0200 fixed display of GxsTrans statistics
27774ba csoler Thu, 29 Jun 2017 22:13:04 +0200 Merge pull request #911 from csoler/v0.6-GxsTransport
b294b4b csoler Thu, 29 Jun 2017 22:11:44 +0200 changed sorting of popular forums w.r.t. time of last post rather than number of supplier friends
a864cf7 csoler Thu, 29 Jun 2017 21:12:42 +0200 Merge pull request #910 from csoler/v0.6-GxsTransport
4b94b2e csoler Thu, 29 Jun 2017 21:12:02 +0200 improved display of GxsTrans statistics
1b4e8a4 csoler Thu, 29 Jun 2017 18:38:10 +0200 Merge pull request #909 from csoler/v0.6-GxsTransport
64e3fc9 csoler Thu, 29 Jun 2017 18:37:39 +0200 fixed bug preventing correct subscribe in GxsTrans
700d114 csoler Thu, 29 Jun 2017 18:27:00 +0200 fixed bug causing failure of group autosubscribe in GxsTrans
cb31a92 csoler Thu, 29 Jun 2017 18:03:31 +0200 Merge pull request #907 from PhenomRetroShare/Add_GeneralDirectDLSetting
b4071d1 Phenom Mon, 26 Jun 2017 23:35:01 +0200 Add General Direct Download setting.
a3e8b96 csoler Thu, 29 Jun 2017 13:50:41 +0200 Merge pull request #908 from csoler/v0.6-GxsTransport
37edcc1 csoler Thu, 29 Jun 2017 13:44:40 +0200 fixed subscribe policy to GxsTrans groups as a function of last available post and group usage
dc605c0 csoler Thu, 29 Jun 2017 13:15:39 +0200 added a last modif TS in GrpNetworkStats, that is inited from network Grp statistics, and used to provide a value for unsubscribed groups
533e2a8 csoler Wed, 28 Jun 2017 23:23:27 +0200 added check to fix existing wrong storage time value in GxsTrans
f37ba83 csoler Wed, 28 Jun 2017 23:12:33 +0200 moved msg keep period settings to netService and made the initialisation obei the default settings of the service
b96effb csoler Wed, 28 Jun 2017 22:37:50 +0200 Merge pull request #895 from PhenomRetroShare/Add_HelpInRelayTab
3550971 csoler Wed, 28 Jun 2017 22:37:05 +0200 Merge pull request #902 from Emotyco/libresapi_avatar_handlers
12b5628 csoler Tue, 27 Jun 2017 22:21:35 +0200 added more debug info in GxsUtil
51c7e18 csoler Tue, 27 Jun 2017 19:56:21 +0200 added last msg time in GxsTrans stats. Added mutex to protect non atomic mPreferredGroup
579c944 csoler Sun, 25 Jun 2017 21:50:51 +0200 Merge pull request #903 from sehraf/improve-server-page
3c54beb sehraf Sun, 25 Jun 2017 19:19:07 +0200 hide hidden service port for I2P instead of just disabling it (it's not used for I2P)
e128fcb Konrad Sun, 25 Jun 2017 15:35:23 +0200 Added: Creating identity with avatar in libresapi
54166ce Konrad Sun, 25 Jun 2017 14:30:38 +0200 Added: Handling requests to set and get identity avatar
c3a78ce csoler Sat, 24 Jun 2017 13:14:24 +0200 Merge pull request #900 from csoler/v0.6-GxsTransport
8c4396c csoler Sat, 24 Jun 2017 12:54:06 +0200 Merge pull request #899 from Emotyco/libresapi_wrong_password_notification
66a9dad Konrad Sat, 24 Jun 2017 12:05:32 +0200 Fixed: Information about wrong password
2aac999 Konrad Sat, 24 Jun 2017 12:02:28 +0200 Fixed: Duplication of handler declaration
332fedd csoler Sat, 24 Jun 2017 11:38:48 +0200 fixed mismatched free/delete[] in AvatarDefs
2bb49f6 csoler Fri, 23 Jun 2017 21:58:54 +0200 Merge pull request #898 from csoler/v0.6-GxsTransport
0f99647 csoler Fri, 23 Jun 2017 21:58:17 +0200 fixed memory leak in GxsTrans
25a71c9 csoler Fri, 23 Jun 2017 21:24:37 +0200 Merge pull request #897 from PhenomRetroShare/Fix_ChannelPostButton
adfc594 Phenom Fri, 23 Jun 2017 20:33:43 +0200 Fix GxsChannelPostItem button, like "download" or "Play" never shown.
c415e11 Phenom Thu, 22 Jun 2017 18:52:03 +0200 Add help in Relay setting tab.
07ecbec csoler Thu, 22 Jun 2017 18:05:39 +0200 fixed bug in makeSourcePackage which would always grab the release branch
-- Retroshare Dev Team <contact@retroshare.net> Sat, 01 Jul 2017 16:00:00 +0100
retroshare06 (0.6.2-1.20170623.07ecbec6~precise) precise; urgency=low
c34165e csoler Wed, 21 Jun 2017 08:08:29 +0200 pushed new changelog to force update of the date...
8950acc csoler Thu, 22 Jun 2017 00:39:03 +0200 Merge pull request #892 from PhenomRetroShare/Add_MoveRelayPageToNetwork
ea8af8a Phenom Wed, 21 Jun 2017 17:57:14 +0200 Move Relay setting page to network one.
8cc82f9 csoler Wed, 21 Jun 2017 18:32:51 +0200 Merge pull request #891 from PhenomRetroShare/Fix_MessageToHeight
812e606 csoler Tue, 20 Jun 2017 23:40:58 +0200 fixed changelog for typo
1f9320c csoler Tue, 20 Jun 2017 21:17:21 +0200 updated changelog
310c848 csoler Wed, 21 Jun 2017 07:42:15 +0200 Merge pull request #890 from G10h4ck/qml_app_identity_avatar
c46c747 Phenom Wed, 21 Jun 2017 06:35:29 +0200 Fix To, Cc & Bcc height in MessageWidget.
1d03191 Gioacc Tue, 20 Jun 2017 17:16:27 +0200 Created a dedicated component for avatar image
8c62c2a Gioacc Tue, 20 Jun 2017 15:35:05 +0200 Qml app: show contact avatar in details if available
b206015 Gioacc Tue, 20 Jun 2017 15:33:28 +0200 libresapi: expose identity avatar in JSON API
0133be7 csoler Sat, 17 Jun 2017 23:07:10 +0200 Merge pull request #887 from csoler/v0.6-GxsTransport
12a4529 csoler Sat, 17 Jun 2017 23:02:28 +0200 added ifdef for comments on GxsTrans
eb4bb5b csoler Sat, 17 Jun 2017 21:42:00 +0200 fixed bug in gxs trans stats counting
43dcddc csoler Fri, 16 Jun 2017 12:37:09 +0200 Merge pull request #880 from PhenomRetroShare/Add_GxsCircleNotify
a29bc44 csoler Fri, 16 Jun 2017 12:24:45 +0200 Merge pull request #874 from G10h4ck/silent_initiate_distant_chat_api
12eed8e csoler Fri, 16 Jun 2017 12:22:57 +0200 Merge pull request #884 from sehraf/pr-fix-bob-settings
25565a7 csoler Thu, 15 Jun 2017 23:58:29 +0200 merged upstream/master
6633b04 csoler Thu, 15 Jun 2017 23:57:02 +0200 changed constants for GxsTransport anti-spam
26bb865 csoler Thu, 15 Jun 2017 19:32:31 +0200 added code to reject messages based on existing per-user statistics
65ab68b sehraf Thu, 15 Jun 2017 07:20:24 +0200 fix stop button being wrongly disabled
fe5ec8b sehraf Thu, 15 Jun 2017 07:06:52 +0200 reduce BOB log level
09ff94c csoler Wed, 14 Jun 2017 23:19:52 +0200 added new virtual method to refuse incoming msgs (similar to groups) in RsGenExchange, and used it in p3GxsTrans to refuse msgs from peers who send too much
c451d3a csoler Mon, 12 Jun 2017 22:18:34 +0200 Merge pull request #873 from RetroPooh/tunnstats
1e7feec csoler Mon, 12 Jun 2017 22:16:46 +0200 Merge pull request #882 from topcat/iss879
79825eb csoler Mon, 12 Jun 2017 20:36:02 +0200 fixed thread issue in RsGxsCleanupThread that caused random crashes
80ec9b7 Jeetu Mon, 12 Jun 2017 15:51:26 +0530 Included QStringList header in ApiServerLocal.cpp [Issue 879]
aa64c4d Phenom Tue, 30 May 2017 22:23:31 +0200 Add Circle Feed Item.
1766087 csoler Wed, 7 Jun 2017 23:10:59 +0200 fixed update notification and display in GxsTransStatistics
9853b53 csoler Wed, 7 Jun 2017 23:10:24 +0200 fixed debug output in GxsNetService
7691a8e csoler Wed, 7 Jun 2017 21:41:20 +0200 removed debug info
4cb7522 csoler Wed, 7 Jun 2017 21:41:00 +0200 added deleted gxs messages to the reject list of GxsNetService to avoid re-downloading them right away
edd82d0 Gioacc Wed, 7 Jun 2017 21:37:03 +0200 libresapi: stop assuming first chat message is own
318ea31 csoler Sat, 3 Jun 2017 10:30:22 +0200 fixed layout of GxsTrans stats
23156ab csoler Sat, 3 Jun 2017 10:30:02 +0200 fixed malloc problem when chat avatar is missing
e726bd1 csoler Wed, 7 Jun 2017 13:37:38 +0200 attempt to fix the crash in DataStore by not calling deleteMsgs directly
39f003f csoler Tue, 6 Jun 2017 22:00:08 +0200 Merge pull request #875 from csoler/v0.6-GxsTransport
528317d Gioacc Tue, 6 Jun 2017 18:57:32 +0200 libresapi: silent /chat/initiate_distant_chat
f62028b csoler Tue, 6 Jun 2017 00:15:06 +0200 moved metadata info to members of OutgoingRecord, so that the un-serialized meta is not lost when saved. Ensured backward compatibility when reloading old items.
1e652d6 csoler Mon, 5 Jun 2017 22:27:54 +0200 reduced number of calls to indicateConfigChanged(), and renamed mIngoingQueue into mIncomingQueue in GxsTrans
0098433 csoler Mon, 5 Jun 2017 21:51:59 +0200 Merge pull request #871 from Emotyco/changed_socket_path_windows
b7c09bd csoler Mon, 5 Jun 2017 21:15:42 +0200 added calls to indicateConfigChanged() to force saving GxsTrans outgoing records when updated
2d8fd07 RetroP Mon, 5 Jun 2017 14:25:09 +0300 stats tunnels rearranged columns for better readablilty
ca1dc9d Konrad Sun, 4 Jun 2017 22:10:41 +0200 Changed: Unified socket path across systems.
318b2cb csoler Sun, 4 Jun 2017 20:38:20 +0200 Merge pull request #870 from BabushkaRetroShare/master
7fb0419 Babush Sun, 4 Jun 2017 20:34:10 +0200 Typo fixes
458e180 csoler Sun, 4 Jun 2017 18:44:26 +0200 Merge pull request #869 from csoler/v0.6-GxsTransport
1967204 csoler Sun, 4 Jun 2017 18:43:12 +0200 restored GXS trans cleanign delay
831b560 csoler Sun, 4 Jun 2017 18:37:38 +0200 moved deletion of msgs in GxsTransport inside the service thread
5eaab25 csoler Sat, 3 Jun 2017 20:00:54 +0200 Merge pull request #833 from Emotyco/libresapi_network_configuration
861dab3 csoler Sat, 3 Jun 2017 13:27:21 +0200 Merge pull request #863 from G10h4ck/qmlapp_pex_alpha
e3cd3b6 csoler Fri, 2 Jun 2017 23:26:24 +0200 fixed bug causing display of null group in GxsTransportStatistics
fb7ac7a csoler Fri, 2 Jun 2017 23:10:43 +0200 fixed mismatched free/delete (free is used in rschatitems.cc to delete avatars)
efdfa46 Gioacc Fri, 2 Jun 2017 10:39:42 +0200 Merge branch 'libresapi_attempt_connection' into qmlapp_pex_alpha
8b72c9c Gioacc Fri, 2 Jun 2017 10:26:15 +0200 libresapi expose connection attempt method
8e7e700 csoler Thu, 1 Jun 2017 10:16:30 +0200 fixed compilation for windows
59b77da Gioacc Wed, 31 May 2017 12:11:15 +0200 Merge branch 'master' into qmlapp_pex_alpha
1ebcc60 csoler Tue, 30 May 2017 22:22:06 +0200 Merge pull request #861 from RetroShare/v0.6-GxsTransport
d7797f1 csoler Tue, 30 May 2017 21:42:29 +0200 Merge pull request #856 from G10h4ck/GxsTransOptionalChat
eacf23d csoler Tue, 30 May 2017 21:40:41 +0200 Merge pull request #860 from csoler/v0.6-GxsTransport
832ba69 csoler Tue, 30 May 2017 21:38:59 +0200 fixed up cleanup for GxsTransport
a7eb167 csoler Tue, 30 May 2017 20:57:20 +0200 fixed a bug in RsThread which made finished threads unaware of their state
32ad43a csoler Tue, 30 May 2017 20:46:49 +0200 Merge pull request #859 from PhenomRetroShare/Fix_StartDialogMargin
5410c51 csoler Tue, 30 May 2017 20:45:39 +0200 added cleanup thread for GxsTransport
34fbee2 Phenom Tue, 30 May 2017 20:34:12 +0200 Fix StartDialog margins.
5c71d52 Gioacc Tue, 30 May 2017 15:43:43 +0200 async chat disabled by default in GUI
f4c167c csoler Tue, 30 May 2017 13:57:11 +0200 improved display of GXS Transport stats
2e3f62a csoler Mon, 29 May 2017 23:06:31 +0200 added msg ids to GxsTransport statistics.
bd1edbc csoler Sun, 28 May 2017 22:50:34 +0200 Merge pull request #850 from csoler/v0.6-GxsTransport
0868b64 csoler Sun, 28 May 2017 22:49:07 +0200 fixed uninitialized memory read in GxsTrans msg Id
4c07050 csoler Sun, 28 May 2017 22:02:14 +0200 Merge pull request #841 from sehraf/pr-minor-fix
048045a csoler Sun, 28 May 2017 22:01:28 +0200 Merge pull request #849 from PhenomRetroShare/Fix_logo_web_nobackground
54e91e3 csoler Sun, 28 May 2017 22:00:49 +0200 Merge pull request #840 from felisucoibi/master
9121ff6 csoler Sun, 28 May 2017 21:59:48 +0200 Merge pull request #848 from PhenomRetroShare/Fix_WindowsCompil
9d2e0d7 Phenom Sun, 28 May 2017 15:19:27 +0200 Fix Appveyor
5c99297 Phenom Sun, 28 May 2017 13:19:22 +0200 Fix logo_web_nobackground
28119b5 Phenom Sun, 28 May 2017 12:57:36 +0200 Fix Windows Compilation
6d76624 csoler Sat, 27 May 2017 23:16:20 +0200 fixed uninitialized memory read in grouter
e0498ba csoler Sat, 27 May 2017 22:37:14 +0200 Merge pull request #846 from csoler/v0.6-GxsTransport
eea63ac csoler Sat, 27 May 2017 22:19:52 +0200 minor code cleaning in p3GxsTrans (struct->class for consistency, sendMail->sendData), added popularity+subscribed status display in statistics
753867e csoler Sat, 27 May 2017 15:22:32 +0200 Merge pull request #845 from csoler/v0.6-GxsTransport
6da8b2a csoler Sat, 27 May 2017 15:13:23 +0200 fixed up icons in statistics window
e06bd9b csoler Sat, 27 May 2017 14:48:08 +0200 added icon for GxsTransport
4fef4d6 csoler Sat, 27 May 2017 14:23:16 +0200 added display of the various GxsTrans groups and their respective sizes
7c43998 csoler Fri, 26 May 2017 22:04:33 +0200 Merge pull request #842 from csoler/v0.6-GxsTransport
541b42a sehraf Fri, 26 May 2017 20:29:43 +0200 minor fix
a3096f2 csoler Fri, 26 May 2017 20:28:44 +0200 added data hash to GxsTrans display
95b0273 felisu Fri, 26 May 2017 18:54:02 +0200 small fix removed ... from text login screen.
4fa6cbe csoler Fri, 26 May 2017 18:42:52 +0200 fixed display in GxsTrans stats widget
95f1719 felisu Fri, 26 May 2017 18:37:05 +0200 Changed login screen add Profile/Node text.
1e8df12 felisu Fri, 26 May 2017 18:19:06 +0200 Final step to change again size and design of start up login screen. 4/4
7281222 felisu Fri, 26 May 2017 18:15:14 +0200 Login screen 3 / 4
2dbe3a1 felisu Fri, 26 May 2017 18:13:57 +0200 Start login 2/4
0fa3b9e felisu Fri, 26 May 2017 18:12:24 +0200 smaller login screen and less blue 1
873131f csoler Thu, 25 May 2017 22:20:18 +0200 Merge pull request #836 from sehraf/pr-add-i2p-bob-v2.1
14b9a54 csoler Thu, 25 May 2017 16:56:29 +0200 added group data retrieval to GxsTransStatistics
a3ee85a sehraf Sun, 9 Oct 2016 14:32:52 +0200 Add I2P BOB support to libretroashare and RetroShare GUI
9ff81b9 csoler Tue, 23 May 2017 22:06:46 +0200 Merge pull request #835 from felisucoibi/master
483d538 defnax Tue, 23 May 2017 18:46:50 +0200 fit the background image to the login page
a136fb6 csoler Mon, 22 May 2017 23:54:55 +0200 added display of ongoing record status for GxsTrans. Unfinished.
ac66ee7 felisu Mon, 22 May 2017 15:21:06 +0200 Improved GUI gencert
9b67e93 Konrad Sun, 21 May 2017 19:51:52 +0200 Added: Network configuration to libresapi.
fbeb6ff csoler Sun, 21 May 2017 15:57:10 +0200 added infrastructure for gathering statistics about GxsTransport. Unfinished.
8c1babe csoler Sun, 21 May 2017 15:12:49 +0200 Merge pull request #832 from felisucoibi/master
2adde95 felisu Sun, 21 May 2017 15:08:07 +0200 fixed bad uploading of previous pr
dbc2396 csoler Sun, 21 May 2017 14:52:20 +0200 Merge pull request #830 from Gottox/fix-libressl
6bc72dd felisu Sun, 21 May 2017 14:51:43 +0200 restored start dialog and fixed
33ab7fa csoler Sun, 21 May 2017 14:49:13 +0200 Merge pull request #831 from Gottox/fix-musl
b341fea csoler Sun, 21 May 2017 13:49:41 +0200 merged upstream/master
a5cebb9 felisu Sun, 21 May 2017 12:35:43 +0200 simplified and upgraded gui logo added
ecf3fc5 felisu Sun, 21 May 2017 12:34:52 +0200 simplified gui
d83c42d felisu Sun, 21 May 2017 12:33:40 +0200 Add files via upload
a578acd Enno B Sun, 21 May 2017 10:54:19 +0200 fix building with musl libc
2046d9e Enno B Sun, 21 May 2017 10:48:58 +0200 fix building with libressl
95c9b37 defnax Sun, 21 May 2017 04:12:34 +0200 update background image resolution
a439fbf csoler Sat, 20 May 2017 23:01:56 +0200 fixed bug (due to new serializer) that caused a wrong hash to be computed when sending distant messages
ef59a60 csoler Sat, 20 May 2017 22:39:53 +0200 Merge pull request #828 from csoler/v0.6-EditPosts
162095b csoler Sat, 20 May 2017 22:37:31 +0200 fixed count of unread/new posts by not counting older versions
8b079f8 csoler Sat, 20 May 2017 18:34:07 +0200 Merge pull request #827 from csoler/v0.6-EditPosts
0321037 csoler Sat, 20 May 2017 18:15:57 +0200 fixed centering of comments
7a2807a defnax Sat, 20 May 2017 18:06:23 +0200 added missed icon
9da1e1c csoler Sat, 20 May 2017 17:53:25 +0200 fixed proper comment number in channels feeds
51710c1 csoler Sat, 20 May 2017 17:33:05 +0200 merge comments between channel item versions
bda7a50 defnax Sat, 20 May 2017 15:14:43 +0200 Improved look & feel for Generate and Login Window
d79c117 csoler Fri, 19 May 2017 22:12:02 +0200 Merge pull request #826 from PhenomRetroShare/Fix_ChatFontSetting
7acefda Phenom Fri, 19 May 2017 18:40:17 +0200 Fix Chat Font setting saving.
6b09fa0 csoler Thu, 18 May 2017 22:31:52 +0200 allow GxsFeedItems to have versions. Unfinished (does not compile)
db3dad3 Gioacc Thu, 18 May 2017 21:57:24 +0200 Local API binary output support + qml image example
e59366d Gioacc Wed, 17 May 2017 15:49:26 +0200 Qml app: made contact sorting case insensitive
97a0e00 Gioacc Wed, 17 May 2017 15:34:29 +0200 Qml Better debugging for token manager
c1c1d5d Gioacc Wed, 17 May 2017 15:33:10 +0200 Qml app: fixed unread messages count displaying
d5ec641 csoler Tue, 16 May 2017 19:45:27 +0200 changing background color as a function of commenter ID (needs to be further adapted to all styles)
86118d9 csoler Tue, 16 May 2017 10:26:03 +0200 Merge pull request #823 from csoler/v0.6-EditPosts
fd136c1 csoler Tue, 16 May 2017 10:24:23 +0200 made gxs comments multi-lines
b9d19c2 csoler Mon, 15 May 2017 22:17:26 +0200 Merge pull request #822 from csoler/v0.6-EditPosts
2bc36bc csoler Mon, 15 May 2017 22:13:36 +0200 properly merge new version feed items in channels when some items are already present
84e588b csoler Mon, 15 May 2017 21:37:22 +0200 switch file to REMOTE state in subfileitem if the attachment has already been checked in the past but the file is not here anymore
635918e csoler Mon, 15 May 2017 20:09:58 +0200 Merge pull request #821 from G10h4ck/v0.6-GxsTransport
de9a44f Gioacc Mon, 15 May 2017 19:16:08 +0200 Merge branch 'v0.6-GxsTransport' into qmlapp_pex_alpha
10ec527 Gioacc Mon, 15 May 2017 15:00:21 +0200 Fix GxsTrans related serialization regressions
745462a Gioacc Mon, 15 May 2017 15:05:07 +0200 Merge branch 'v0.6-GxsTransport' into qmlapp_pex_alpha
93a6b7d Gioacc Mon, 15 May 2017 15:00:21 +0200 Fix serialization regression in async chat
d335d45 thunder2 Mon, 15 May 2017 09:43:47 +0200 Fixed build script for Windows
32b7003 csoler Sun, 14 May 2017 21:44:08 +0200 Merge pull request #820 from csoler/v0.6-EditPosts
18e37de csoler Sun, 14 May 2017 21:41:26 +0200 hide download buttons when the file is local in sub file item
1824da1 csoler Sun, 14 May 2017 21:29:04 +0200 Merge pull request #819 from csoler/v0.6-EditPosts
f832f3d csoler Sun, 14 May 2017 21:26:45 +0200 added delete button to channel attached files
af57545 csoler Sun, 14 May 2017 20:59:43 +0200 removed unused button in GxsChannelPostsWidget
9077d80 csoler Sun, 14 May 2017 17:52:40 +0200 Merge pull request #817 from csoler/v0.6-EditPosts
2f43927 csoler Sat, 13 May 2017 21:13:24 +0200 Merge pull request #698 from G10h4ck/gxs_mail_experiments
c0c5cc5 csoler Sat, 13 May 2017 21:08:16 +0200 Merge branch 'master' into gxs_mail_experiments
01bb4b0 csoler Sat, 13 May 2017 20:41:56 +0200 added ifdefs around debug info and fixed a few bugs in channel post edit
6859e0d csoler Sat, 13 May 2017 17:13:05 +0200 fixed post replacement algorithm in channel editing
022c545 Gioacc Sat, 13 May 2017 12:52:45 +0200 Qml app: show contact details when avater clicked
0b82b73 Gioacc Sat, 13 May 2017 11:43:31 +0200 Qml app: fixed import/export of plain certificate
659e3c9 csoler Fri, 12 May 2017 23:55:09 +0200 merged upstream/master
305c5d6 csoler Fri, 12 May 2017 23:54:02 +0200 added collapsing of new versions of channel posts
2f17a80 defnax Fri, 12 May 2017 21:39:50 +0200 added missed icons
837fcd7 defnax Fri, 12 May 2017 18:29:39 +0200 Added Placeholder text for Password field, removed "Password:" label.
5044ac1 csoler Thu, 11 May 2017 23:44:57 +0200 moved the edit button from top bar to each channel post
5406da9 csoler Thu, 11 May 2017 23:21:13 +0200 first part of channel post editing
38d0743 csoler Thu, 11 May 2017 18:46:40 +0200 used more saturated colors in stats graph
7a19dee csoler Thu, 11 May 2017 14:52:26 +0200 small fix to statistics view
eb30af5 csoler Thu, 11 May 2017 14:42:06 +0200 improved display in bw statistics
d73e850 defnax Thu, 11 May 2017 18:14:21 +0200 look n feel improvements
7eb5e8e csoler Wed, 10 May 2017 21:37:06 +0200 added warning when switching opmode status to non turtle for the first time
1ff1b89 Phenom Sun, 7 Feb 2016 11:45:55 +0100 Save last state of OpMode status bar droplist and restore it at start.
3cc79fb csoler Wed, 10 May 2017 20:00:42 +0200 Merge pull request #774 from PhenomRetroShare/Fix_LobbyTopic
af18e4c csoler Wed, 10 May 2017 19:34:53 +0200 Merge pull request #816 from PhenomRetroShare/Fix_StartPasswordFocus
6ffae36 Phenom Wed, 10 May 2017 19:06:03 +0200 Fix Start page password focus.
11708c8 csoler Tue, 9 May 2017 22:44:00 +0200 Merge pull request #814 from csoler/v0.6-ImprovedGUI
bd9a8ae csoler Tue, 9 May 2017 22:39:15 +0200 prevent to remove old forum messages that have follow-ups.
5d7d8c0 csoler Tue, 9 May 2017 21:56:22 +0200 Merge pull request #813 from csoler/v0.6-ImprovedGUI
52a0aea csoler Tue, 9 May 2017 21:33:02 +0200 fixed bug causing edited posts to turn into missing messages when they have submessages
0edbc26 csoler Tue, 9 May 2017 19:34:48 +0200 Merge pull request #812 from PhenomRetroShare/Fix_TextColorGrayForumThread
a5386eb Phenom Tue, 9 May 2017 19:19:13 +0200 Fix text's color gray in Forum thread when selected.
0af05d2 csoler Tue, 9 May 2017 19:06:31 +0200 patch to avoid re-asking for rejected plugins when the executable is upgraded.
88525e4 csoler Tue, 9 May 2017 18:55:28 +0200 Merge pull request #811 from PhenomRetroShare/Add_OpenCertFileInHomeAddFriend
237db96 Phenom Mon, 8 May 2017 17:26:12 +0200 Add Open Cert File in Home Add Friend wizard.
34dd68d csoler Mon, 8 May 2017 23:05:16 +0200 Merge pull request #809 from csoler/v0.6-FT
e0cb0f4 csoler Mon, 8 May 2017 23:04:04 +0200 fixed previous commit
9a0df3f csoler Mon, 8 May 2017 22:21:28 +0200 Merge pull request #804 from PhenomRetroShare/Fix_Warnings
9a7f78f csoler Mon, 8 May 2017 22:18:51 +0200 Merge pull request #805 from PhenomRetroShare/Fix_Commit_#77adc82
caa36b4 csoler Mon, 8 May 2017 22:17:09 +0200 Merge pull request #807 from PhenomRetroShare/Fix_ToasterPositionSetting
d74bb2a csoler Mon, 8 May 2017 22:16:39 +0200 Merge pull request #806 from PhenomRetroShare/Fix_LobbySoundNotification
4a2f5f0 csoler Mon, 8 May 2017 22:02:38 +0200 Merge pull request #808 from csoler/v0.6-FT
8a86b9e csoler Mon, 8 May 2017 22:00:51 +0200 added a per-friend upload slots limit in FT. Default is 0=unlimited
39646f3 Gioacc Mon, 8 May 2017 20:44:15 +0200 qml app removed unused icon
d0b881f Gioacc Mon, 8 May 2017 20:35:15 +0200 Added view to show/edit contact details
52a04e1 csoler Mon, 8 May 2017 18:24:32 +0200 updated ubuntu changelog
f67617a Gioacc Mon, 8 May 2017 16:57:37 +0200 Add override and final placeolders for old GCC compatibility
d02cba5 Phenom Sun, 16 Apr 2017 17:53:37 +0200 Fix Lobby Topic not send on invite.
594ab53 Phenom Mon, 8 May 2017 15:37:18 +0200 Fix Toaster Position Setting.
a869a37 Phenom Mon, 8 May 2017 15:29:11 +0200 Fix Lobby's sound notification.
79bbe0e Phenom Mon, 8 May 2017 14:53:53 +0200 Fix Commit #77adc82
ccaf488 Gioacc Mon, 8 May 2017 13:38:29 +0200 Merge branch 'master' into qmlapp_pex_alpha
4a2f688 Phenom Mon, 8 May 2017 13:01:34 +0200 Fix Windows Compilation:
8f30634 Gioacc Mon, 8 May 2017 12:33:40 +0200 Merge branch 'gxs_mail_experiments' into qmlapp_pex_alpha
5022ef0 Phenom Mon, 8 May 2017 12:26:37 +0200 Fix Warnings: this if clause does not guard...
f352939 Phenom Mon, 8 May 2017 12:25:29 +0200 Fix Warnings:
bf47edf Phenom Mon, 8 May 2017 12:22:46 +0200 Fix Warnings:
523730f Phenom Mon, 8 May 2017 12:21:08 +0200 Fix Warnings: unused parameter resp, 'req' & 'resp'
a6acc72 Phenom Mon, 8 May 2017 12:18:51 +0200 Fix Warnings: this if clause does not guard...
58c812a Phenom Mon, 8 May 2017 12:17:01 +0200 Fix Warnings: unused parameter s
ee7e92d Phenom Mon, 8 May 2017 12:15:45 +0200 Fix Warnings: this if clause does not guard...
9b1209d Phenom Mon, 8 May 2017 12:14:04 +0200 Fix Warnings: unused parameter s & 'n'
91e3cc3 Phenom Mon, 8 May 2017 12:08:29 +0200 Fix Warnings: variable p set but not used
ca291b7 Phenom Mon, 8 May 2017 12:05:58 +0200 Fix Warnings: warning: unused variable i2d
9021609 Phenom Mon, 8 May 2017 11:55:23 +0200 Fix Warnings: unused variable p
7892004 Phenom Mon, 8 May 2017 11:53:16 +0200 Fix Warnings: unused parameter member_name
381aca4 Phenom Mon, 8 May 2017 11:49:39 +0200 Fix Warnings: unused parameter j, 'ctx' & 'name'
dd089a9 Phenom Mon, 8 May 2017 11:46:54 +0200 Fix Warnings: this if clause does not guard
5050d4f Phenom Mon, 8 May 2017 11:42:49 +0200 Fix Warnings: unused parameter indent warning: unused parameter indent [-Wunused-parameter] virtual std::ostream& print(std::ostream &out, uint16_t indent = 0) { return out; } // derived from RsItem, but should be removed
8e9b3c9 Gioacc Mon, 8 May 2017 12:03:42 +0200 Fix missing include
add529f csoler Mon, 8 May 2017 11:41:34 +0200 Merge pull request #803 from PhenomRetroShare/Fix_UnitTest
4e2db2f Phenom Mon, 8 May 2017 11:30:54 +0200 Fix UnitTest
-- Retroshare Dev Team <contact@retroshare.net> Mon, 20 Jun 2017 22:00:00 +0100
retroshare06 (0.6.2-1.20170508.52a04e1f~precise) precise; urgency=low
9714409 csoler Mon, 8 May 2017 10:57:00 +0200 Merge pull request #802 from csoler/v0.6-ImprovedGUI
de0f8b9 csoler Mon, 8 May 2017 10:51:15 +0200 moved passphrase box into start dialog, and removed blank logo, replaced it by RS splash logo
6cb4990 csoler Mon, 8 May 2017 10:06:40 +0200 fixed compilation with qt4

View File

@ -4,7 +4,7 @@
version="0.6.2"
gitpath="https://github.com/RetroShare/RetroShare.git"
workdir=retroshare06-${version}
branch="v0.6.2-official_release"
branch="master"
#bubba3="Y" # comment out to compile for bubba3
######################################################

View File

@ -16,6 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QStringList>
#include "ApiServerLocal.h"
#include "JsonStream.h"

View File

@ -161,6 +161,7 @@ ChatHandler::ChatHandler(StateTokenServer *sts, RsNotify *notify, RsMsgs *msgs,
mMsgStateToken = mStateTokenServer->getNewToken();
mLobbiesStateToken = mStateTokenServer->getNewToken();
mUnreadMsgsStateToken = mStateTokenServer->getNewToken();
mInvitationsStateToken = mStateTokenServer->getNewToken();
addResourceHandler("*", this, &ChatHandler::handleWildcard);
addResourceHandler("lobbies", this, &ChatHandler::handleLobbies);
@ -169,6 +170,9 @@ ChatHandler::ChatHandler(StateTokenServer *sts, RsNotify *notify, RsMsgs *msgs,
addResourceHandler("unsubscribe_lobby", this, &ChatHandler::handleUnsubscribeLobby);
addResourceHandler("autosubscribe_lobby", this, &ChatHandler::handleAutoSubsribeLobby);
addResourceHandler("clear_lobby", this, &ChatHandler::handleClearLobby);
addResourceHandler("invite_to_lobby", this, &ChatHandler::handleInviteToLobby);
addResourceHandler("get_invitations_to_lobby", this, &ChatHandler::handleGetInvitationsToLobby);
addResourceHandler("answer_to_invitation", this, &ChatHandler::handleAnswerToInvitation);
addResourceHandler("lobby_participants", this, &ChatHandler::handleLobbyParticipants);
addResourceHandler("messages", this, &ChatHandler::handleMessages);
addResourceHandler("send_message", this, &ChatHandler::handleSendMessage);
@ -229,6 +233,15 @@ void ChatHandler::notifyChatLobbyEvent(uint64_t lobby_id, uint32_t event_type,
}
}
void ChatHandler::notifyListChange(int list, int type)
{
if(list == NOTIFY_LIST_CHAT_LOBBY_INVITATION)
{
RS_STACK_MUTEX(mMtx); /********** LOCKED **********/
mStateTokenServer->replaceToken(mInvitationsStateToken);
}
}
void ChatHandler::tick()
{
RS_STACK_MUTEX(mMtx); /********** LOCKED **********/
@ -266,7 +279,8 @@ void ChatHandler::tick()
else
{
LobbyParticipantsInfo& pi = mit->second;
if(!std::equal(pi.participants.begin(), pi.participants.end(), info.gxs_ids.begin()))
if(!std::equal(pi.participants.begin(), pi.participants.end(), info.gxs_ids.begin())
|| pi.participants.size() != info.gxs_ids.size())
{
pi.participants = info.gxs_ids;
mStateTokenServer->replaceToken(pi.state_token);
@ -414,16 +428,18 @@ void ChatHandler::tick()
}
}
else if(msg.chat_id.isDistantChatId())
{
RsIdentityDetails details;
DistantChatPeerInfo dcpinfo ;
if(!gxs_id_failed && rsMsgs->getDistantChatStatus(msg.chat_id.toDistantChatId(),dcpinfo)
&& mRsIdentity->getIdDetails(msg.incoming? dcpinfo.to_id: dcpinfo.own_id, details))
{
info.remote_author_id = details.mId.toStdString();
info.remote_author_name = details.mNickname;
}
{
RsIdentityDetails details;
DistantChatPeerInfo dcpinfo;
if( !gxs_id_failed &&
rsMsgs->getDistantChatStatus(
msg.chat_id.toDistantChatId(), dcpinfo ) &&
mRsIdentity->getIdDetails(dcpinfo.to_id, details) )
{
info.remote_author_id = details.mId.toStdString();
info.remote_author_name = details.mNickname;
}
else
{
gxs_id_failed = true;
@ -933,6 +949,70 @@ void ChatHandler::handleClearLobby(Request &req, Response &resp)
resp.setOk();
}
void ChatHandler::handleInviteToLobby(Request& req, Response& resp)
{
std::string chat_id;
std::string pgp_id;
req.mStream << makeKeyValueReference("chat_id", chat_id);
req.mStream << makeKeyValueReference("pgp_id", pgp_id);
ChatId chatId(chat_id);
RsPgpId pgpId(pgp_id);
std::list<RsPeerId> peerIds;
mRsPeers->getAssociatedSSLIds(pgpId, peerIds);
for(std::list<RsPeerId>::iterator it = peerIds.begin(); it != peerIds.end(); it++)
mRsMsgs->invitePeerToLobby(chatId.toLobbyId(), (*it));
resp.setOk();
}
void ChatHandler::handleGetInvitationsToLobby(Request& req, Response& resp)
{
std::list<ChatLobbyInvite> invites;
mRsMsgs->getPendingChatLobbyInvites(invites);
resp.mDataStream.getStreamToMember();
for(std::list<ChatLobbyInvite>::const_iterator it = invites.begin(); it != invites.end(); ++it)
{
resp.mDataStream.getStreamToMember()
<< makeKeyValue("peer_id", (*it).peer_id.toStdString())
<< makeKeyValue("lobby_id", (*it).lobby_id)
<< makeKeyValue("lobby_name", (*it).lobby_name)
<< makeKeyValue("lobby_topic", (*it).lobby_topic);
}
resp.mStateToken = mInvitationsStateToken;
resp.setOk();
}
void ChatHandler::handleAnswerToInvitation(Request& req, Response& resp)
{
ChatLobbyId lobbyId = 0;
req.mStream << makeKeyValueReference("lobby_id", lobbyId);
bool join;
req.mStream << makeKeyValueReference("join", join);
std::string gxs_id;
req.mStream << makeKeyValueReference("gxs_id", gxs_id);
RsGxsId gxsId(gxs_id);
if(join)
{
if(rsMsgs->acceptLobbyInvite(lobbyId, gxsId))
resp.setOk();
else
resp.setFail();
}
else
{
rsMsgs->denyLobbyInvite(lobbyId);
resp.setOk();
}
}
ResponseTask* ChatHandler::handleLobbyParticipants(Request &req, Response &resp)
{
RS_STACK_MUTEX(mMtx); /********** LOCKED **********/
@ -1199,9 +1279,9 @@ void ChatHandler::handleInitiateDistantChatConnexion(Request& req, Response& res
DistantChatPeerId distant_chat_id;
uint32_t error_code;
if(mRsMsgs->initiateDistantChatConnexion(receiver_id, sender_id,
distant_chat_id, error_code))
resp.setOk();
if(mRsMsgs->initiateDistantChatConnexion( receiver_id, sender_id,
distant_chat_id, error_code,
false )) resp.setOk();
else resp.setFail("Failed to initiate distant chat");
ChatId chat_id(distant_chat_id);

View File

@ -35,6 +35,8 @@ public:
virtual void notifyChatLobbyEvent (uint64_t /* lobby id */, uint32_t /* event type */ ,
const RsGxsId& /* nickname */,const std::string& /* any string */);
virtual void notifyListChange(int list, int type);
// from tickable
virtual void tick();
@ -122,6 +124,9 @@ private:
void handleSubscribeLobby(Request& req, Response& resp);
void handleUnsubscribeLobby(Request& req, Response& resp);
void handleAutoSubsribeLobby(Request& req, Response& resp);
void handleInviteToLobby(Request& req, Response& resp);
void handleGetInvitationsToLobby(Request& req, Response& resp);
void handleAnswerToInvitation(Request& req, Response& resp);
void handleClearLobby(Request& req, Response& resp);
ResponseTask* handleLobbyParticipants(Request& req, Response& resp);
void handleMessages(Request& req, Response& resp);
@ -162,6 +167,7 @@ private:
std::map<ChatLobbyId, LobbyParticipantsInfo> mLobbyParticipantsInfos;
StateToken mUnreadMsgsStateToken;
StateToken mInvitationsStateToken;
};
} // namespace resource_api

View File

@ -22,6 +22,7 @@
#include <retroshare/rsidentity.h>
#include <retroshare/rspeers.h>
#include <util/radix64.h>
#include <time.h>
#include "Operators.h"
@ -86,6 +87,15 @@ protected:
<< makeKeyValueReference("name", params.nickname)
<< makeKeyValueReference("pgp_linked", params.isPgpLinked);
std::string avatar;
req.mStream << makeKeyValueReference("avatar", avatar);
std::vector<uint8_t> avatar_data = Radix64::decode(avatar);
uint8_t *p_avatar_data = &avatar_data[0];
uint32_t size = avatar_data.size();
params.mImage.clear();
params.mImage.copy(p_avatar_data, size);
if(params.nickname == "")
{
resp.setFail("name can't be empty");
@ -163,9 +173,6 @@ IdentityHandler::IdentityHandler(StateTokenServer *sts, RsNotify *notify,
addResourceHandler("notown_ids", this,
&IdentityHandler::handleNotOwnIdsRequest);
addResourceHandler("create_identity", this,
&IdentityHandler::handleCreateIdentity);
addResourceHandler("export_key", this, &IdentityHandler::handleExportKey);
addResourceHandler("import_key", this, &IdentityHandler::handleImportKey);
@ -177,6 +184,9 @@ IdentityHandler::IdentityHandler(StateTokenServer *sts, RsNotify *notify,
addResourceHandler("get_identity_details", this, &IdentityHandler::handleGetIdentityDetails);
addResourceHandler("get_avatar", this, &IdentityHandler::handleGetAvatar);
addResourceHandler("set_avatar", this, &IdentityHandler::handleSetAvatar);
addResourceHandler("set_ban_node", this, &IdentityHandler::handleSetBanNode);
addResourceHandler("set_opinion", this, &IdentityHandler::handleSetOpinion);
}
@ -500,6 +510,11 @@ void IdentityHandler::handleGetIdentityDetails(Request& req, Response& resp)
RsIdentityDetails details;
mRsIdentity->getIdDetails(RsGxsId(data.mMeta.mGroupId), details);
std::string base64Avatar;
Radix64::encode(details.mAvatar.mData, details.mAvatar.mSize, base64Avatar);
resp.mDataStream << makeKeyValue("avatar", base64Avatar);
StreamBase& usagesStream = resp.mDataStream.getStreamToMember("usages");
usagesStream.getStreamToMember();
@ -514,6 +529,89 @@ void IdentityHandler::handleGetIdentityDetails(Request& req, Response& resp)
resp.setOk();
}
void IdentityHandler::handleSetAvatar(Request& req, Response& resp)
{
std::string gxs_id;
std::string avatar;
req.mStream << makeKeyValueReference("gxs_id", gxs_id);
req.mStream << makeKeyValueReference("avatar", avatar);
RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
uint32_t token;
std::list<RsGxsGroupId> groupIds;
groupIds.push_back(RsGxsGroupId(gxs_id));
mRsIdentity->getTokenService()->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds);
time_t start = time(NULL);
while((mRsIdentity->getTokenService()->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
&&(mRsIdentity->getTokenService()->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_FAILED)
&&((time(NULL) < (start+10)))
)
{
#ifdef WINDOWS_SYS
Sleep(500);
#else
usleep(500*1000);
#endif
}
RsGxsIdGroup data;
std::vector<RsGxsIdGroup> datavector;
if (!mRsIdentity->getGroupData(token, datavector))
{
resp.setFail();
return;
}
if(datavector.empty())
{
resp.setFail();
return;
}
data = datavector[0];
if(!avatar.empty())
{
std::vector<uint8_t> avatar_data = Radix64::decode(avatar);
uint8_t *p_avatar_data = &avatar_data[0];
uint32_t size = avatar_data.size();
data.mImage.clear();
data.mImage.copy(p_avatar_data, size);
std::string base64Avatar;
Radix64::encode(data.mImage.mData, data.mImage.mSize, base64Avatar);
resp.mDataStream << makeKeyValue("avatar", base64Avatar);
}
else
data.mImage.clear();
uint32_t dummyToken = 0;
mRsIdentity->updateIdentity(dummyToken, data);
resp.setOk();
}
void IdentityHandler::handleGetAvatar(Request& req, Response& resp)
{
std::string gxs_id;
req.mStream << makeKeyValueReference("gxs_id", gxs_id);
RsIdentityDetails details;
bool got = mRsIdentity->getIdDetails(RsGxsId(gxs_id), details);
std::string base64Avatar;
Radix64::encode(details.mAvatar.mData, details.mAvatar.mSize, base64Avatar);
resp.mDataStream << makeKeyValue("avatar", base64Avatar);
if(got)
resp.setOk();
else
resp.setFail();
}
void IdentityHandler::handleSetBanNode(Request& req, Response& resp)
{
std::string pgp_id;

View File

@ -53,6 +53,9 @@ private:
void handleGetIdentityDetails(Request& req, Response& resp);
void handleGetAvatar(Request& req, Response& resp);
void handleSetAvatar(Request& req, Response& resp);
void handleSetBanNode(Request& req, Response& resp);
void handleSetOpinion(Request& req, Response& resp);

View File

@ -1,3 +1,23 @@
/*
* libresapi
*
* Copyright (C) 2015 electron128 <electron128@yahoo.com>
* Copyright (C) 2017 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PeersHandler.h"
#include <retroshare/rspeers.h>
@ -5,6 +25,7 @@
#include <util/radix64.h>
#include <retroshare/rsstatus.h>
#include <retroshare/rsiface.h>
#include <retroshare/rsconfig.h>
#include <algorithm>
@ -194,15 +215,19 @@ PeersHandler::PeersHandler(StateTokenServer* sts, RsNotify* notify, RsPeers *pee
mNotify->registerNotifyClient(this);
mStateTokenServer->registerTickClient(this);
addResourceHandler("*", this, &PeersHandler::handleWildcard);
addResourceHandler("attempt_connection", this, &PeersHandler::handleAttemptConnection);
addResourceHandler("get_state_string", this, &PeersHandler::handleGetStateString);
addResourceHandler("set_state_string", this, &PeersHandler::handleSetStateString);
addResourceHandler("get_custom_state_string", this, &PeersHandler::handleGetCustomStateString);
addResourceHandler("set_custom_state_string", this, &PeersHandler::handleSetCustomStateString);
addResourceHandler("get_network_options", this, &PeersHandler::handleGetNetworkOptions);
addResourceHandler("set_network_options", this, &PeersHandler::handleSetNetworkOptions);
addResourceHandler("get_pgp_options", this, &PeersHandler::handleGetPGPOptions);
addResourceHandler("set_pgp_options", this, &PeersHandler::handleSetPGPOptions);
addResourceHandler("get_node_options", this, &PeersHandler::handleGetNodeOptions);
addResourceHandler("set_node_options", this, &PeersHandler::handleSetNodeOptions);
addResourceHandler("examine_cert", this, &PeersHandler::handleExamineCert);
}
PeersHandler::~PeersHandler()
@ -576,19 +601,30 @@ void PeersHandler::handleWildcard(Request &req, Response &resp)
}
RsPeerId peer_id;
RsPgpId pgp_id;
std::string cleanCert;
int error_code;
std::string error_string;
if(mRsPeers->loadCertificateFromString(cert_string, peer_id, pgp_id, error_string)
&& mRsPeers->addFriend(peer_id, pgp_id, flags))
{
ok = true;
resp.mDataStream << makeKeyValueReference("pgp_id", pgp_id);
resp.mDataStream << makeKeyValueReference("peer_id", peer_id);
}
else
{
resp.mDebug << "Error: failed to add peer" << std::endl;
resp.mDebug << error_string << std::endl;
}
if (mRsPeers->cleanCertificate(cert_string, cleanCert, error_code))
{
if(mRsPeers->loadCertificateFromString(cert_string, peer_id, pgp_id, error_string)
&& mRsPeers->addFriend(peer_id, pgp_id, flags))
{
ok = true;
resp.mDataStream << makeKeyValueReference("pgp_id", pgp_id);
resp.mDataStream << makeKeyValueReference("peer_id", peer_id);
}
else
{
resp.mDebug << "Error: failed to add peer" << std::endl;
resp.mDebug << error_string << std::endl;
}
}
else
{
resp.mDebug << "Error: failed to add peer" << std::endl;
resp.mDebug << error_code << std::endl;
}
}
}
if(ok)
@ -601,6 +637,19 @@ void PeersHandler::handleWildcard(Request &req, Response &resp)
}
}
void PeersHandler::handleAttemptConnection(Request &req, Response &resp)
{
std::string ssl_peer_id;
req.mStream << makeKeyValueReference("peer_id", ssl_peer_id);
RsPeerId peerId(ssl_peer_id);
if(peerId.isNull()) resp.setFail("Invalid peer_id");
else
{
mRsPeers->connectAttempt(peerId);
resp.setOk();
}
}
void PeersHandler::handleExamineCert(Request &req, Response &resp)
{
std::string cert_string;
@ -618,6 +667,198 @@ void PeersHandler::handleExamineCert(Request &req, Response &resp)
}
}
void PeersHandler::handleGetNetworkOptions(Request& req, Response& resp)
{
RsPeerDetails detail;
if (!mRsPeers->getPeerDetails(mRsPeers->getOwnId(), detail))
return;
resp.mDataStream << makeKeyValue("local_address", detail.localAddr);
resp.mDataStream << makeKeyValue("local_port", (int)detail.localPort);
resp.mDataStream << makeKeyValue("external_address", detail.extAddr);
resp.mDataStream << makeKeyValue("external_port", (int)detail.extPort);
resp.mDataStream << makeKeyValue("dyn_dns", detail.dyndns);
int netIndex = 0;
switch(detail.netMode)
{
case RS_NETMODE_EXT:
netIndex = 2;
break;
case RS_NETMODE_UDP:
netIndex = 1;
break;
case RS_NETMODE_UPNP:
netIndex = 0;
break;
}
resp.mDataStream << makeKeyValue("nat_mode", netIndex);
int discoveryIndex = 3; // NONE.
if(detail.vs_dht != RS_VS_DHT_OFF)
{
if(detail.vs_disc != RS_VS_DISC_OFF)
discoveryIndex = 0; // PUBLIC
else
discoveryIndex = 2; // INVERTED
}
else
{
if(detail.vs_disc != RS_VS_DISC_OFF)
discoveryIndex = 1; // PRIVATE
else
discoveryIndex = 3; // NONE
}
resp.mDataStream << makeKeyValue("discovery_mode", discoveryIndex);
int dlrate = 0;
int ulrate = 0;
rsConfig->GetMaxDataRates(dlrate, ulrate);
resp.mDataStream << makeKeyValue("download_limit", dlrate);
resp.mDataStream << makeKeyValue("upload_limit", ulrate);
bool checkIP = mRsPeers->getAllowServerIPDetermination();
resp.mDataStream << makeKeyValue("check_ip", checkIP);
StreamBase& previousIPsStream = resp.mDataStream.getStreamToMember("previous_ips");
previousIPsStream.getStreamToMember();
for(std::list<std::string>::const_iterator it = detail.ipAddressList.begin(); it != detail.ipAddressList.end(); ++it)
previousIPsStream.getStreamToMember() << makeKeyValue("ip_address", *it);
std::list<std::string> ip_servers;
mRsPeers->getIPServersList(ip_servers);
StreamBase& websitesStream = resp.mDataStream.getStreamToMember("websites");
websitesStream.getStreamToMember();
for(std::list<std::string>::const_iterator it = ip_servers.begin(); it != ip_servers.end(); ++it)
websitesStream.getStreamToMember() << makeKeyValue("website", *it);
std::string proxyaddr;
uint16_t proxyport;
uint32_t status ;
// Tor
mRsPeers->getProxyServer(RS_HIDDEN_TYPE_TOR, proxyaddr, proxyport, status);
resp.mDataStream << makeKeyValue("tor_address", proxyaddr);
resp.mDataStream << makeKeyValue("tor_port", (int)proxyport);
// I2P
mRsPeers->getProxyServer(RS_HIDDEN_TYPE_I2P, proxyaddr, proxyport, status);
resp.mDataStream << makeKeyValue("i2p_address", proxyaddr);
resp.mDataStream << makeKeyValue("i2p_port", (int)proxyport);
resp.setOk();
}
void PeersHandler::handleSetNetworkOptions(Request& req, Response& resp)
{
RsPeerDetails detail;
if (!mRsPeers->getPeerDetails(mRsPeers->getOwnId(), detail))
return;
int netIndex = 0;
uint32_t natMode = 0;
req.mStream << makeKeyValueReference("nat_mode", netIndex);
switch(netIndex)
{
case 3:
natMode = RS_NETMODE_HIDDEN;
break;
case 2:
natMode = RS_NETMODE_EXT;
break;
case 1:
natMode = RS_NETMODE_UDP;
break;
default:
case 0:
natMode = RS_NETMODE_UPNP;
break;
}
if (detail.netMode != natMode)
mRsPeers->setNetworkMode(mRsPeers->getOwnId(), natMode);
int discoveryIndex;
uint16_t vs_disc = 0;
uint16_t vs_dht = 0;
req.mStream << makeKeyValueReference("discovery_mode", discoveryIndex);
switch(discoveryIndex)
{
case 0:
vs_disc = RS_VS_DISC_FULL;
vs_dht = RS_VS_DHT_FULL;
break;
case 1:
vs_disc = RS_VS_DISC_FULL;
vs_dht = RS_VS_DHT_OFF;
break;
case 2:
vs_disc = RS_VS_DISC_OFF;
vs_dht = RS_VS_DHT_FULL;
break;
case 3:
default:
vs_disc = RS_VS_DISC_OFF;
vs_dht = RS_VS_DHT_OFF;
break;
}
if ((vs_disc != detail.vs_disc) || (vs_dht != detail.vs_dht))
mRsPeers->setVisState(mRsPeers->getOwnId(), vs_disc, vs_dht);
if (0 != netIndex)
{
std::string localAddr;
int localPort;
std::string extAddr;
int extPort;
req.mStream << makeKeyValueReference("local_address", localAddr);
req.mStream << makeKeyValueReference("local_port", localPort);
req.mStream << makeKeyValueReference("external_address", extAddr);
req.mStream << makeKeyValueReference("external_port", extPort);
mRsPeers->setLocalAddress(mRsPeers->getOwnId(), localAddr, (uint16_t)localPort);
mRsPeers->setExtAddress(mRsPeers->getOwnId(), extAddr, (uint16_t)extPort);
}
std::string dynDNS;
req.mStream << makeKeyValueReference("dyn_dns", dynDNS);
mRsPeers->setDynDNS(mRsPeers->getOwnId(), dynDNS);
int dlrate = 0;
int ulrate = 0;
req.mStream << makeKeyValueReference("download_limit", dlrate);
req.mStream << makeKeyValueReference("upload_limit", ulrate);
rsConfig->SetMaxDataRates(dlrate, ulrate);
bool checkIP;
req.mStream << makeKeyValueReference("check_ip", checkIP);
rsPeers->allowServerIPDetermination(checkIP) ;
// Tor
std::string toraddr;
int torport;
req.mStream << makeKeyValueReference("tor_address", toraddr);
req.mStream << makeKeyValueReference("tor_port", torport);
mRsPeers->setProxyServer(RS_HIDDEN_TYPE_TOR, toraddr, (uint16_t)torport);
// I2P
std::string i2paddr;
int i2pport;
req.mStream << makeKeyValueReference("i2p_address", i2paddr);
req.mStream << makeKeyValueReference("i2p_port", i2pport);
mRsPeers->setProxyServer(RS_HIDDEN_TYPE_I2P, i2paddr, (uint16_t)i2pport);
resp.mStateToken = getCurrentStateToken();
resp.setOk();
}
void PeersHandler::handleGetPGPOptions(Request& req, Response& resp)
{
std::string pgp_id;

View File

@ -1,4 +1,23 @@
#pragma once
/*
* libresapi
*
* Copyright (C) 2015 electron128 <electron128@yahoo.com>
* Copyright (C) 2017 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ResourceRouter.h"
#include "StateTokenServer.h"
@ -33,8 +52,11 @@ public:
virtual void notifyUnreadMsgCountChanged(const RsPeerId& peer, uint32_t count);
private:
void handleWildcard(Request& req, Response& resp);
void handleExamineCert(Request& req, Response& resp);
void handleWildcard(Request& req, Response& resp);
void handleAttemptConnection(Request& req, Response& resp);
void handleExamineCert(Request& req, Response& resp);
void handleGetStateString(Request& req, Response& resp);
void handleSetStateString(Request& req, Response& resp);
@ -42,6 +64,9 @@ private:
void handleGetCustomStateString(Request& req, Response& resp);
void handleSetCustomStateString(Request& req, Response& resp);
void handleGetNetworkOptions(Request& req, Response& resp);
void handleSetNetworkOptions(Request& req, Response& resp);
void handleGetPGPOptions(Request& req, Response& resp);
void handleSetPGPOptions(Request& req, Response& resp);

View File

@ -26,6 +26,7 @@ RsControlModule::RsControlModule(int argc, char **argv, StateTokenServer* sts, A
mAutoLoginNextTime(false),
mWantPassword(false),
mPrevIsBad(false),
mCountAttempts(0),
mPassword("")
{
mStateToken = sts->getNewToken();
@ -64,7 +65,14 @@ bool RsControlModule::askForPassword(const std::string &title, const std::string
{
RS_STACK_MUTEX(mDataMtx); // ********** LOCKED **********
mPrevIsBad = prev_is_bad;
mCountAttempts++;
if(mCountAttempts == 3)
{
mPrevIsBad = prev_is_bad;
mCountAttempts = 0;
}
else
mPrevIsBad = false;
if(mFixedPassword != "")
{

View File

@ -78,7 +78,8 @@ private:
// to notify that a password callback is waiting
// to answer the request, clear the flag and set the password
bool mWantPassword;
bool mPrevIsBad ;
bool mPrevIsBad;
int mCountAttempts;
std::string mTitle;
std::string mKeyName;
std::string mPassword;

View File

@ -146,7 +146,7 @@ class p3ChatService::AvatarInfo
~AvatarInfo()
{
delete[] _image_data ;
free( _image_data );
_image_data = NULL ;
_image_size = 0 ;
}
@ -159,7 +159,7 @@ class p3ChatService::AvatarInfo
void init(const unsigned char *jpeg_data,int size)
{
_image_size = size ;
_image_data = new unsigned char[size] ;
_image_data = (unsigned char*)rs_malloc(size) ;
memcpy(_image_data,jpeg_data,size) ;
}
AvatarInfo(const unsigned char *jpeg_data,int size)
@ -169,7 +169,13 @@ class p3ChatService::AvatarInfo
void toUnsignedChar(unsigned char *& data,uint32_t& size) const
{
data = new unsigned char[_image_size] ;
if(_image_size == 0)
{
size = 0 ;
data = NULL ;
return ;
}
data = (unsigned char *)rs_malloc(_image_size) ;
size = _image_size ;
memcpy(data,_image_data,size*sizeof(unsigned char)) ;
}

View File

@ -99,24 +99,27 @@ ftFileControl::ftFileControl(std::string fname,
}
ftController::ftController(ftDataMultiplex *dm, p3ServiceControl *sc, uint32_t ftServiceId)
: p3Config(),
last_save_time(0),
last_clean_time(0),
mDataplex(dm),
mTurtle(NULL),
mFtServer(NULL),
mServiceCtrl(sc),
mFtServiceType(ftServiceId),
ctrlMutex("ftController"),
doneMutex("ftController"),
mFtActive(false),
mDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE)
: p3Config(),
last_save_time(0),
last_clean_time(0),
mSearch(NULL),
mDataplex(dm),
mExtraList(NULL),
mTurtle(NULL),
mFtServer(NULL),
mServiceCtrl(sc),
mFtServiceType(ftServiceId),
mDefaultEncryptionPolicy(RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE),
mFilePermDirectDLPolicy(RS_FILE_PERM_DIRECT_DL_PER_USER),
cnt(0),
ctrlMutex("ftController"),
doneMutex("ftController"),
mFtActive(false),
mFtPendingDone(false),
mDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE),
_max_active_downloads(5), // default queue size
_max_uploads_per_friend(FT_FILECONTROL_MAX_UPLOAD_SLOTS_DEFAULT)
{
_max_active_downloads = 5 ; // default queue size
mDefaultEncryptionPolicy = RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE;
_max_uploads_per_friend = FT_FILECONTROL_MAX_UPLOAD_SLOTS_DEFAULT ;
/* TODO */
cnt = 0 ;
}
void ftController::setTurtleRouter(p3turtle *pt) { mTurtle = pt ; }
@ -278,18 +281,27 @@ void ftController::data_tick()
void ftController::searchForDirectSources()
{
RsStackMutex stack(ctrlMutex); /******* LOCKED ********/
if (!mSearch) return;
for(std::map<RsFileHash,ftFileControl*>::iterator it(mDownloads.begin()); it != mDownloads.end(); ++it)
if(it->second->mState != ftFileControl::QUEUED && it->second->mState != ftFileControl::PAUSED)
{
FileInfo info ; // info needs to be re-allocated each time, to start with a clear list of peers (it's not cleared down there)
for(std::map<RsFileHash,ftFileControl*>::iterator it(mDownloads.begin()); it != mDownloads.end(); ++it )
if(it->second->mState != ftFileControl::QUEUED && it->second->mState != ftFileControl::PAUSED )
{
FileInfo info ; // Info needs to be re-allocated each time, to start with a clear list of peers (it's not cleared down there)
if(mSearch->search(it->first, RS_FILE_HINTS_REMOTE | RS_FILE_HINTS_SPEC_ONLY, info))
for(std::list<TransferInfo>::const_iterator pit = info.peers.begin(); pit != info.peers.end(); ++pit)
if(rsPeers->servicePermissionFlags(pit->peerId) & RS_NODE_PERM_DIRECT_DL)
if(it->second->mTransfer->addFileSource(pit->peerId)) /* if the sources don't exist already - add in */
setPeerState(it->second->mTransfer, pit->peerId, FT_CNTRL_STANDARD_RATE, mServiceCtrl->isPeerConnected(mFtServiceType, pit->peerId));
}
if( mSearch->search(it->first, RS_FILE_HINTS_REMOTE | RS_FILE_HINTS_SPEC_ONLY, info) )
for( std::list<TransferInfo>::const_iterator pit = info.peers.begin(); pit != info.peers.end(); ++pit )
{
bool bAllowDirectDL = false;
switch (rsFiles->filePermDirectDL()) {
case RS_FILE_PERM_DIRECT_DL_YES: bAllowDirectDL = true; break;
case RS_FILE_PERM_DIRECT_DL_NO: bAllowDirectDL = false; break;
default:bAllowDirectDL = (rsPeers->servicePermissionFlags(pit->peerId) & RS_NODE_PERM_DIRECT_DL); break;
}
if( bAllowDirectDL )
if( it->second->mTransfer->addFileSource(pit->peerId) ) /* if the sources don't exist already - add in */
setPeerState( it->second->mTransfer, pit->peerId, FT_CNTRL_STANDARD_RATE, mServiceCtrl->isPeerConnected(mFtServiceType, pit->peerId) );
}
}
}
void ftController::tickTransfers()
@ -748,7 +760,8 @@ bool ftController::completeFile(const RsFileHash& hash)
std::cerr << std::endl;
#endif
mExtraList->addExtraFile(path, hash, size, period, extraflags);
if(mExtraList)
mExtraList->addExtraFile(path, hash, size, period, extraflags);
}
else
{
@ -855,6 +868,7 @@ bool ftController::alreadyHaveFile(const RsFileHash& hash, FileInfo &info)
return true ;
// check for file lists
if (!mSearch) return false;
if (mSearch->search(hash, RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_SPEC_ONLY, info))
return true ;
@ -944,18 +958,27 @@ bool ftController::FileRequest(const std::string& fname, const RsFileHash& hash
// remove the sources from the list, if they don't have clearance for direct transfer. This happens only for non cache files.
//
for(std::list<RsPeerId>::iterator it = srcIds.begin(); it != srcIds.end(); )
if(!(rsPeers->servicePermissionFlags(*it) & RS_NODE_PERM_DIRECT_DL))
{
std::list<RsPeerId>::iterator tmp(it) ;
++tmp ;
srcIds.erase(it) ;
it = tmp ;
}
else
++it ;
std::list<RsPeerId>::const_iterator it;
for(std::list<RsPeerId>::iterator it = srcIds.begin(); it != srcIds.end(); )
{
bool bAllowDirectDL = false;
switch (rsFiles->filePermDirectDL()) {
case RS_FILE_PERM_DIRECT_DL_YES: bAllowDirectDL = true; break;
case RS_FILE_PERM_DIRECT_DL_NO: bAllowDirectDL = false; break;
default:bAllowDirectDL = (rsPeers->servicePermissionFlags(*it) & RS_NODE_PERM_DIRECT_DL); break;
}
if(!bAllowDirectDL)
{
std::list<RsPeerId>::iterator tmp(it);
++tmp;
srcIds.erase(it);
it = tmp;
}
else
++it;
}
std::list<RsPeerId>::const_iterator it;
std::list<TransferInfo>::const_iterator pit;
#ifdef CONTROL_DEBUG
@ -1001,7 +1024,14 @@ bool ftController::FileRequest(const std::string& fname, const RsFileHash& hash
*/
for(it = srcIds.begin(); it != srcIds.end(); ++it)
if(rsPeers->servicePermissionFlags(*it) & RS_NODE_PERM_DIRECT_DL)
{
bool bAllowDirectDL = false;
switch (rsFiles->filePermDirectDL()) {
case RS_FILE_PERM_DIRECT_DL_YES: bAllowDirectDL = true; break;
case RS_FILE_PERM_DIRECT_DL_NO: bAllowDirectDL = false; break;
default:bAllowDirectDL = (rsPeers->servicePermissionFlags(*it) & RS_NODE_PERM_DIRECT_DL); break;
}
if(bAllowDirectDL)
{
uint32_t i, j;
if ((dit->second)->mTransfer->getPeerState(*it, i, j))
@ -1020,6 +1050,7 @@ bool ftController::FileRequest(const std::string& fname, const RsFileHash& hash
(dit->second)->mTransfer->addFileSource(*it);
setPeerState(dit->second->mTransfer, *it, rate, mServiceCtrl->isPeerConnected(mFtServiceType, *it));
}
}
if (srcIds.empty())
{
@ -1034,7 +1065,7 @@ bool ftController::FileRequest(const std::string& fname, const RsFileHash& hash
} /******* UNLOCKED ********/
if(!(flags & RS_FILE_REQ_NO_SEARCH))
if(mSearch && !(flags & RS_FILE_REQ_NO_SEARCH))
{
/* do a source search - for any extra sources */
// add sources only in direct mode
@ -1056,7 +1087,14 @@ bool ftController::FileRequest(const std::string& fname, const RsFileHash& hash
#endif
// Because this is auto-add, we only add sources that we allow to DL from using direct transfers.
if ((srcIds.end() == std::find( srcIds.begin(), srcIds.end(), pit->peerId)) && (RS_NODE_PERM_DIRECT_DL & rsPeers->servicePermissionFlags(pit->peerId)))
bool bAllowDirectDL = false;
switch (rsFiles->filePermDirectDL()) {
case RS_FILE_PERM_DIRECT_DL_YES: bAllowDirectDL = true; break;
case RS_FILE_PERM_DIRECT_DL_NO: bAllowDirectDL = false; break;
default:bAllowDirectDL = (rsPeers->servicePermissionFlags(pit->peerId) & RS_NODE_PERM_DIRECT_DL); break;
}
if ((srcIds.end() == std::find( srcIds.begin(), srcIds.end(), pit->peerId)) && bAllowDirectDL)
{
srcIds.push_back(pit->peerId);
@ -1729,6 +1767,7 @@ const std::string max_uploads_per_friend_ss("MAX_UPLOADS_PER_FRIEND");
const std::string default_chunk_strategy_ss("DEFAULT_CHUNK_STRATEGY");
const std::string free_space_limit_ss("FREE_SPACE_LIMIT");
const std::string default_encryption_policy_ss("DEFAULT_ENCRYPTION_POLICY");
const std::string file_perm_direct_dl_ss("FILE_PERM_DIRECT_DL");
/* p3Config Interface */
@ -1779,6 +1818,15 @@ bool ftController::saveList(bool &cleanup, std::list<RsItem *>& saveData)
configMap[default_encryption_policy_ss] = (mDefaultEncryptionPolicy==RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE)?"PERMISSIVE":"STRICT" ;
switch (mFilePermDirectDLPolicy) {
case RS_FILE_PERM_DIRECT_DL_YES: configMap[file_perm_direct_dl_ss] = "YES" ;
break;
case RS_FILE_PERM_DIRECT_DL_NO: configMap[file_perm_direct_dl_ss] = "NO" ;
break;
default: configMap[file_perm_direct_dl_ss] = "PER_USER" ;
break;
}
rs_sprintf(s, "%lu", RsDiscSpace::freeSpaceLimit());
configMap[free_space_limit_ss] = s ;
@ -1995,9 +2043,9 @@ bool ftController::loadConfigMap(std::map<std::string, std::string> &configMap)
{
std::map<std::string, std::string>::iterator mit;
std::string str_true("true");
std::string empty("");
std::string dir = "notempty";
//std::string str_true("true");
//std::string empty("");
//std::string dir = "notempty";
if (configMap.end() != (mit = configMap.find(download_dir_ss)))
setDownloadDirectory(mit->second);
@ -2072,6 +2120,26 @@ bool ftController::loadConfigMap(std::map<std::string, std::string> &configMap)
_max_uploads_per_friend = n ;
}
}
if(configMap.end() != (mit = configMap.find(file_perm_direct_dl_ss)))
{
if(mit->second == "YES")
{
mFilePermDirectDLPolicy = RS_FILE_PERM_DIRECT_DL_YES ;
std::cerr << "Note: loading default value for file permission direct download: YES" << std::endl;
}
else if(mit->second == "NO")
{
mFilePermDirectDLPolicy = RS_FILE_PERM_DIRECT_DL_NO ;
std::cerr << "Note: loading default value for file permission direct download: NO" << std::endl;
}
else if(mit->second == "PER_USER")
{
mFilePermDirectDLPolicy = RS_FILE_PERM_DIRECT_DL_PER_USER ;
std::cerr << "Note: loading default value for file permission direct download: PER_USER" << std::endl;
}
}
return true;
}
@ -2097,6 +2165,22 @@ uint32_t ftController::defaultEncryptionPolicy()
RsStackMutex stack(ctrlMutex); /******* LOCKED ********/
return mDefaultEncryptionPolicy ;
}
void ftController::setFilePermDirectDL(uint32_t perm)
{
RsStackMutex stack(ctrlMutex); /******* LOCKED ********/
if (mFilePermDirectDLPolicy != perm)
{
mFilePermDirectDLPolicy = perm;
IndicateConfigChanged();
}
}
uint32_t ftController::filePermDirectDL()
{
RsStackMutex stack(ctrlMutex); /******* LOCKED ********/
return mFilePermDirectDLPolicy;
}
void ftController::setFreeDiskSpaceLimit(uint32_t size_in_mb)
{
RsDiscSpace::setFreeSpaceLimit(size_in_mb) ;

View File

@ -149,6 +149,9 @@ class ftController: public RsTickingThread, public pqiServiceMonitor, public p3C
void setMaxUploadsPerFriend(uint32_t m) ;
uint32_t getMaxUploadsPerFriend() ;
void setFilePermDirectDL(uint32_t perm) ;
uint32_t filePermDirectDL() ;
bool FileCancel(const RsFileHash& hash);
bool FileControl(const RsFileHash& hash, uint32_t flags);
bool FileClearCompleted();
@ -237,7 +240,8 @@ class ftController: public RsTickingThread, public pqiServiceMonitor, public p3C
ftServer *mFtServer ;
p3ServiceControl *mServiceCtrl;
uint32_t mFtServiceType;
uint32_t mDefaultEncryptionPolicy ;
uint32_t mDefaultEncryptionPolicy;
uint32_t mFilePermDirectDLPolicy;
uint32_t cnt ;
RsMutex ctrlMutex;

View File

@ -291,18 +291,28 @@ bool ftServer::activateTunnels(const RsFileHash& hash,uint32_t encryption_policy
return true ;
}
bool ftServer::setDestinationName(const RsFileHash& hash,const std::string& name)
{
return mFtController->setDestinationName(hash,name);
}
bool ftServer::setDestinationDirectory(const RsFileHash& hash,const std::string& directory)
{
return mFtController->setDestinationDirectory(hash,directory);
}
bool ftServer::setDestinationName(const RsFileHash& hash,const std::string& name)
{
return mFtController->setDestinationName(hash,name);
}
bool ftServer::setChunkStrategy(const RsFileHash& hash,FileChunksInfo::ChunkStrategy s)
{
return mFtController->setChunkStrategy(hash,s);
}
void ftServer::setDefaultChunkStrategy(FileChunksInfo::ChunkStrategy s)
{
mFtController->setDefaultChunkStrategy(s) ;
}
FileChunksInfo::ChunkStrategy ftServer::defaultChunkStrategy()
{
return mFtController->defaultChunkStrategy() ;
}
uint32_t ftServer::freeDiskSpaceLimit()const
{
return mFtController->freeDiskSpaceLimit() ;
@ -311,9 +321,10 @@ void ftServer::setFreeDiskSpaceLimit(uint32_t s)
{
mFtController->setFreeDiskSpaceLimit(s) ;
}
void ftServer::setDefaultChunkStrategy(FileChunksInfo::ChunkStrategy s)
void ftServer::setDefaultEncryptionPolicy(uint32_t s)
{
mFtController->setDefaultChunkStrategy(s) ;
mFtController->setDefaultEncryptionPolicy(s) ;
}
uint32_t ftServer::defaultEncryptionPolicy()
{
@ -329,14 +340,15 @@ uint32_t ftServer::getMaxUploadSlotsPerFriend()
return mFtController->getMaxUploadsPerFriend() ;
}
void ftServer::setDefaultEncryptionPolicy(uint32_t s)
void ftServer::setFilePermDirectDL(uint32_t perm)
{
mFtController->setDefaultEncryptionPolicy(s) ;
mFtController->setFilePermDirectDL(perm);
}
FileChunksInfo::ChunkStrategy ftServer::defaultChunkStrategy()
uint32_t ftServer::filePermDirectDL()
{
return mFtController->defaultChunkStrategy() ;
return mFtController->filePermDirectDL() ;
}
bool ftServer::FileCancel(const RsFileHash& hash)
{
// Remove from both queue and ftController, by default.

View File

@ -140,6 +140,8 @@ public:
virtual uint32_t defaultEncryptionPolicy() ;
virtual void setMaxUploadSlotsPerFriend(uint32_t n) ;
virtual uint32_t getMaxUploadSlotsPerFriend() ;
virtual void setFilePermDirectDL(uint32_t perm) ;
virtual uint32_t filePermDirectDL() ;
/***
* Control of Downloads Priority.

View File

@ -359,7 +359,8 @@ bool GxsSecurity::getSignature(const char *data, uint32_t data_len, const RsTlvP
ok &= EVP_SignUpdate(mdctx, data, data_len) == 1;
unsigned int siglen = EVP_PKEY_size(key_priv);
unsigned char sigbuf[siglen] = { 0 };
unsigned char sigbuf[siglen] ;
memset(sigbuf,0,siglen) ;
ok &= EVP_SignFinal(mdctx, sigbuf, &siglen, key_priv) == 1;
// clean up

View File

@ -31,7 +31,7 @@
bool GxsTokenQueue::queueRequest(uint32_t token, uint32_t req_type)
{
RsStackMutex stack(mQueueMtx); /********** STACK LOCKED MTX ******/
RS_STACK_MUTEX(mQueueMtx);
mQueue.push_back(GxsTokenQueueItem(token, req_type));
return true;
}

View File

@ -92,6 +92,7 @@ public:
uint32_t mMaxVisibleCount ;
bool mGrpAutoSync ;
bool mAllowMsgSync;
time_t mLastGroupModificationTS ;
};
typedef std::map<RsGxsGroupId, std::vector<RsNxsMsg*> > NxsMsgDataResult;

View File

@ -70,7 +70,7 @@ static const uint32_t INTEGRITY_CHECK_PERIOD = 60*31; // 31 minutes
RsGenExchange::RsGenExchange(RsGeneralDataService *gds, RsNetworkExchangeService *ns,
RsSerialType *serviceSerialiser, uint16_t servType, RsGixs* gixs,
uint32_t authenPolicy, uint32_t messageStorePeriod)
uint32_t authenPolicy)
: mGenMtx("GenExchange"),
mDataStore(gds),
mNetService(ns),
@ -78,7 +78,6 @@ RsGenExchange::RsGenExchange(RsGeneralDataService *gds, RsNetworkExchangeService
mServType(servType),
mGixs(gixs),
mAuthenPolicy(authenPolicy),
MESSAGE_STORE_PERIOD(messageStorePeriod),
mCleaning(false),
mLastClean((int)time(NULL) - (int)(RSRandom::random_u32() % MSG_CLEANUP_PERIOD)), // this helps unsynchronising the checks for the different services
mMsgCleanUp(NULL),
@ -94,9 +93,7 @@ RsGenExchange::RsGenExchange(RsGeneralDataService *gds, RsNetworkExchangeService
VALIDATE_FAIL_TRY_LATER(2),
VALIDATE_MAX_WAITING_TIME(60)
{
mDataAccess = new RsGxsDataAccess(gds);
}
void RsGenExchange::setNetworkExchangeService(RsNetworkExchangeService *ns)
@ -104,7 +101,9 @@ void RsGenExchange::setNetworkExchangeService(RsNetworkExchangeService *ns)
if(mNetService != NULL)
std::cerr << "(EE) Cannot override existing network exchange service. Make sure it has been deleted otherwise." << std::endl;
else
{
mNetService = ns ;
}
}
RsGenExchange::~RsGenExchange()
@ -190,62 +189,67 @@ void RsGenExchange::tick()
now = time(NULL);
if(mChecking || (mLastCheck + INTEGRITY_CHECK_PERIOD < now))
{
if(mIntegrityCheck)
mLastCheck = time(NULL);
{
if(mIntegrityCheck->isDone())
RS_STACK_MUTEX(mGenMtx) ;
if(!mIntegrityCheck)
{
std::list<RsGxsGroupId> grpIds;
std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > msgIds;
mIntegrityCheck->getDeletedIds(grpIds, msgIds);
if (!grpIds.empty())
{
RS_STACK_MUTEX(mGenMtx) ;
RsGxsGroupChange* gc = new RsGxsGroupChange(RsGxsNotify::TYPE_PROCESSED, false);
gc->mGrpIdList = grpIds;
#ifdef GEN_EXCH_DEBUG
std::cerr << " adding the following grp ids to notification: " << std::endl;
for(std::list<RsGxsGroupId>::const_iterator it(grpIds.begin());it!=grpIds.end();++it)
std::cerr << " " << *it << std::endl;
#endif
mNotifications.push_back(gc);
// also notify the network exchange service that these groups no longer exist.
if(mNetService)
mNetService->removeGroups(grpIds) ;
}
if (!msgIds.empty()) {
RS_STACK_MUTEX(mGenMtx) ;
RsGxsMsgChange* c = new RsGxsMsgChange(RsGxsNotify::TYPE_PROCESSED, false);
c->msgChangeMap = msgIds;
mNotifications.push_back(c);
}
delete mIntegrityCheck;
mIntegrityCheck = NULL;
mLastCheck = time(NULL);
mChecking = false;
mIntegrityCheck = new RsGxsIntegrityCheck(mDataStore,this,mGixs);
mIntegrityCheck->start("gxs integrity");
mChecking = true;
}
}
else
if(mIntegrityCheck->isDone())
{
mIntegrityCheck = new RsGxsIntegrityCheck(mDataStore,this,mGixs);
mIntegrityCheck->start("gxs integrity");
mChecking = true;
RS_STACK_MUTEX(mGenMtx) ;
std::list<RsGxsGroupId> grpIds;
std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > msgIds;
mIntegrityCheck->getDeletedIds(grpIds, msgIds);
if (!grpIds.empty())
{
RsGxsGroupChange* gc = new RsGxsGroupChange(RsGxsNotify::TYPE_PROCESSED, false);
gc->mGrpIdList = grpIds;
#ifdef GEN_EXCH_DEBUG
std::cerr << " adding the following grp ids to notification: " << std::endl;
for(std::list<RsGxsGroupId>::const_iterator it(grpIds.begin());it!=grpIds.end();++it)
std::cerr << " " << *it << std::endl;
#endif
mNotifications.push_back(gc);
// also notify the network exchange service that these groups no longer exist.
if(mNetService)
mNetService->removeGroups(grpIds) ;
}
if (!msgIds.empty())
{
RsGxsMsgChange* c = new RsGxsMsgChange(RsGxsNotify::TYPE_PROCESSED, false);
c->msgChangeMap = msgIds;
mNotifications.push_back(c);
}
delete mIntegrityCheck;
mIntegrityCheck = NULL;
mChecking = false;
}
}
}
bool RsGenExchange::messagePublicationTest(const RsGxsMsgMetaData& meta)
{
time_t st = MESSAGE_STORE_PERIOD;
if(!mNetService)
{
std::cerr << "(EE) No network service in service " << std::hex << serviceType() << std::dec << ": cannot read message storage time." << std::endl;
return false ;
}
if(mNetService)
st = mNetService->getKeepAge(meta.mGroupId, st);
uint32_t st = mNetService->getKeepAge(meta.mGroupId);
time_t storageTimeLimit = meta.mPublishTs + st;
@ -1184,26 +1188,30 @@ bool RsGenExchange::getGroupMeta(const uint32_t &token, std::list<RsGroupMetaDat
std::list<RsGxsGrpMetaData*> metaL;
bool ok = mDataAccess->getGroupSummary(token, metaL);
std::list<RsGxsGrpMetaData*>::iterator lit = metaL.begin();
RsGroupMetaData m;
for(; lit != metaL.end(); ++lit)
for( std::list<RsGxsGrpMetaData*>::iterator lit = metaL.begin(); lit != metaL.end(); ++lit)
{
RsGxsGrpMetaData& gMeta = *(*lit);
m = gMeta;
RsGroupNetworkStats sts ;
if(mNetService != NULL && mNetService->getGroupNetworkStats((*lit)->mGroupId,sts))
{
m.mPop = sts.mSuppliers ;
m.mVisibleMsgCount = sts.mMaxVisibleCount ;
}
else
{
m.mPop= 0 ;
m.mVisibleMsgCount = 0 ;
}
if(mNetService != NULL && mNetService->getGroupNetworkStats(gMeta.mGroupId,sts))
{
m.mPop = sts.mSuppliers ;
m.mVisibleMsgCount = sts.mMaxVisibleCount ;
groupInfo.push_back(m);
if((!(IS_GROUP_SUBSCRIBED(gMeta.mSubscribeFlags))) || gMeta.mLastPost == 0)
m.mLastPost = sts.mLastGroupModificationTS ;
}
else
{
m.mPop= 0 ;
m.mVisibleMsgCount = 0 ;
}
groupInfo.push_back(m);
delete (*lit);
}
@ -1365,6 +1373,14 @@ bool RsGenExchange::getGroupData(const uint32_t &token, std::vector<RsGxsGrpItem
{
gItem->meta.mPop = sts.mSuppliers;
gItem->meta.mVisibleMsgCount = sts.mMaxVisibleCount;
// When the group is not subscribed, the last post value is not updated, because there's no message stored. As a consequence,
// we rely on network statistics to give this value, but it is not as accurate as if it was locally computed, because of blocked
// posts, friends not available, sync delays, etc. Similarly if the group has just been subscribed, the last post info is probably
// uninitialised, so we will it too.
if((!(IS_GROUP_SUBSCRIBED(gItem->meta.mSubscribeFlags))) || gItem->meta.mLastPost == 0)
gItem->meta.mLastPost = sts.mLastGroupModificationTS ;
}
else
{
@ -1372,6 +1388,7 @@ bool RsGenExchange::getGroupData(const uint32_t &token, std::vector<RsGxsGrpItem
gItem->meta.mVisibleMsgCount = 0;
}
// Also check the group privacy flags. A while ago, it as possible to publish a group without privacy flags. Now it is not possible anymore.
// As a consequence, it's important to supply a correct value in this flag before the data can be edited/updated.
@ -1752,8 +1769,18 @@ void RsGenExchange::deleteGroup(uint32_t& token, const RsGxsGroupId& grpId)
}
void RsGenExchange::deleteMsgs(uint32_t& token, const GxsMsgReq& msgs)
{
RS_STACK_MUTEX(mGenMtx) ;
token = mDataAccess->generatePublicToken();
mMsgDeletePublish.push_back(MsgDeletePublish(msgs, token));
// This code below will suspend any requests of the deleted messages for 24 hrs. This of course only works
// if all friend nodes consistently delete the messages in the mean time.
if(mNetService != NULL)
for(GxsMsgReq::const_iterator it(msgs.begin());it!=msgs.end();++it)
for(uint32_t i=0;i<it->second.size();++i)
mNetService->rejectMessage(it->second[i]) ;
}
void RsGenExchange::publishMsg(uint32_t& token, RsGxsMsgItem *msgItem)
@ -1813,10 +1840,12 @@ uint32_t RsGenExchange::getStoragePeriod(const RsGxsGroupId& grpId)
{
RS_STACK_MUTEX(mGenMtx) ;
if(mNetService != NULL)
return mNetService->getKeepAge(grpId,MESSAGE_STORE_PERIOD) ;
else
return MESSAGE_STORE_PERIOD;
if(!mNetService)
{
std::cerr << "(EE) No network service in service " << std::hex << serviceType() << std::dec << ": cannot read message storage time. Returning infinity." << std::endl;
return false ;
}
return mNetService->getKeepAge(grpId) ;
}
void RsGenExchange::setStoragePeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs)
{
@ -2900,8 +2929,12 @@ void RsGenExchange::processRecvdMessages()
std::cerr << " deserialised info: grp id=" << meta->mGroupId << ", msg id=" << meta->mMsgId ;
#endif
uint8_t validateReturn = VALIDATE_FAIL;
bool accept_new_msg = acceptNewMessage(meta,msg->msg.bin_len);
if(ok)
if(!accept_new_msg && mNetService != NULL)
mNetService->rejectMessage(meta->mMsgId) ; // This prevents reloading the message again at next sync.
if(ok && accept_new_msg)
{
std::map<RsGxsGroupId, RsGxsGrpMetaData*>::iterator mit = grpMetas.find(msg->grpId);
@ -3042,8 +3075,8 @@ void RsGenExchange::processRecvdMessages()
mNetService->rejectMessage(*it) ;
}
bool RsGenExchange::acceptNewGroup(const RsGxsGrpMetaData* /*grpMeta*/ )
{ return true; }
bool RsGenExchange::acceptNewGroup(const RsGxsGrpMetaData* /*grpMeta*/ ) { return true; }
bool RsGenExchange::acceptNewMessage(const RsGxsMsgMetaData* /*grpMeta*/,uint32_t size ) { return true; }
void RsGenExchange::processRecvdGroups()
{

View File

@ -117,9 +117,7 @@ public:
* @param gixs This is used for verification of msgs and groups received by Gen Exchange using identities.
* @param authenPolicy This determines the authentication used for verfying authorship of msgs and groups
*/
RsGenExchange(RsGeneralDataService* gds, RsNetworkExchangeService* ns,
RsSerialType* serviceSerialiser, uint16_t mServType, RsGixs* gixs, uint32_t authenPolicy,
uint32_t messageStorePeriod = RS_GXS_DEFAULT_MSG_STORE_PERIOD);
RsGenExchange(RsGeneralDataService* gds, RsNetworkExchangeService* ns, RsSerialType* serviceSerialiser, uint16_t mServType, RsGixs* gixs, uint32_t authenPolicy);
virtual ~RsGenExchange();
@ -260,6 +258,17 @@ public:
*/
virtual bool acceptNewGroup(const RsGxsGrpMetaData *grpMeta) ;
/*!
* \brief acceptNewMessage
* Early checks if the message can be accepted. This is mainly used to check wether the group is for instance overloaded and the service wants
* to put limitations to it.
* Returns true unless derived in GXS services.
*
* \param grpMeta Group metadata to check
* \return
*/
virtual bool acceptNewMessage(const RsGxsMsgMetaData *msgMeta, uint32_t size) ;
bool subscribeToGroup(uint32_t& token, const RsGxsGroupId& grpId, bool subscribe);
/*!
@ -654,7 +663,7 @@ public:
* \brief getDefaultStoragePeriod. All times in seconds.
* \return
*/
virtual uint32_t getDefaultStoragePeriod() { return MESSAGE_STORE_PERIOD; }
virtual uint32_t getDefaultStoragePeriod() { return mNetService->getDefaultKeepAge() ; }
virtual uint32_t getStoragePeriod(const RsGxsGroupId& grpId) ;
virtual void setStoragePeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs) ;
@ -882,8 +891,6 @@ private:
std::vector<GxsPendingItem<RsNxsMsg*, RsGxsGrpMsgIdPair> > mMsgPendingValidate;
typedef std::vector<GxsPendingItem<RsNxsMsg*, RsGxsGrpMsgIdPair> > NxsMsgPendingVect;
const uint32_t MESSAGE_STORE_PERIOD;
bool mCleaning;
time_t mLastClean;
RsGxsMessageCleanUp* mMsgCleanUp;

View File

@ -268,7 +268,7 @@ static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_GXS_KEY_MISSING = 0x05 ;
static const RsPeerId peer_to_print = RsPeerId(std::string("")) ;
static const RsGxsGroupId group_id_to_print = RsGxsGroupId(std::string("")) ; // use this to allow to this group id only, or "" for all IDs
static const uint32_t service_to_print = 0x215 ; // use this to allow to this service id only, or 0 for all services
static const uint32_t service_to_print = RS_SERVICE_TYPE_GXS_TRANS ; // use this to allow to this service id only, or 0 for all services
// warning. Numbers should be SERVICE IDS (see serialiser/rsserviceids.h. E.g. 0x0215 for forums)
class nullstream: public std::ostream {};
@ -311,7 +311,7 @@ RsGxsNetService::RsGxsNetService(uint16_t servType, RsGeneralDataService *gds,
RsNxsNetMgr *netMgr, RsNxsObserver *nxsObs,
const RsServiceInfo serviceInfo,
RsGixsReputation* reputations, RsGcxs* circles, RsGixs *gixs,
PgpAuxUtils *pgpUtils, bool grpAutoSync,bool msgAutoSync)
PgpAuxUtils *pgpUtils, bool grpAutoSync, bool msgAutoSync, uint32_t default_store_period, uint32_t default_sync_period)
: p3ThreadedService(), p3Config(), mTransactionN(0),
mObserver(nxsObs), mDataStore(gds),
mServType(servType), mTransactionTimeOut(TRANSAC_TIMEOUT),
@ -321,11 +321,20 @@ RsGxsNetService::RsGxsNetService(uint16_t servType, RsGeneralDataService *gds,
mCircles(circles), mGixs(gixs),
mReputations(reputations), mPgpUtils(pgpUtils),
mGrpAutoSync(grpAutoSync), mAllowMsgSync(msgAutoSync),
mServiceInfo(serviceInfo)
mServiceInfo(serviceInfo), mDefaultMsgStorePeriod(default_store_period),
mDefaultMsgSyncPeriod(default_sync_period)
{
addSerialType(new RsNxsSerialiser(mServType));
mOwnId = mNetMgr->getOwnId();
mUpdateCounter = 0;
// check the consistency
if(mDefaultMsgStorePeriod > 0 && mDefaultMsgSyncPeriod > mDefaultMsgStorePeriod)
{
std::cerr << "(WW) in GXS service \"" << getServiceInfo().mServiceName << "\": too large message sync period will be set to message store period." << std::endl;
mDefaultMsgSyncPeriod = mDefaultMsgStorePeriod ;
}
}
void RsGxsNetService::getItemNames(std::map<uint8_t,std::string>& names) const
@ -447,6 +456,9 @@ void RsGxsNetService::rejectMessage(const RsGxsMessageId& msg_id)
{
RS_STACK_MUTEX(mNxsMutex) ;
#ifdef NXS_NET_DEBUG_0
GXSNETDEBUG___ << "adding message " << msg_id << " to rejection list for 24hrs." << std::endl;
#endif
mRejectedMessages[msg_id] = time(NULL) ;
}
void RsGxsNetService::cleanRejectedMessages()
@ -595,9 +607,9 @@ void RsGxsNetService::syncWithPeers()
#ifdef NXS_NET_DEBUG_0
GXSNETDEBUG_PG(peerId,grpId) << " peer can send messages for group " << grpId ;
if(!encrypt_to_this_circle_id.isNull())
std::cerr << " request should be encrypted for circle ID " << encrypt_to_this_circle_id << std::endl;
GXSNETDEBUG_PG(peerId,grpId) << " request should be encrypted for circle ID " << encrypt_to_this_circle_id << std::endl;
else
std::cerr << " request should be sent in clear." << std::endl;
GXSNETDEBUG_PG(peerId,grpId) << " request should be sent in clear." << std::endl;
#endif
// On default, the info has never been received so the TS is 0, meaning the peer has sent that it had no information.
@ -620,8 +632,8 @@ void RsGxsNetService::syncWithPeers()
msg->PeerId(peerId);
msg->updateTS = updateTS;
int req_delay = (int)mServerGrpConfigMap[grpId].msg_req_delay ;
int keep_delay = (int)mServerGrpConfigMap[grpId].msg_keep_delay ;
int req_delay = (int)locked_getGrpConfig(grpId).msg_req_delay ;
int keep_delay = (int)locked_getGrpConfig(grpId).msg_keep_delay ;
// If we store for less than we request, we request less, otherwise the posts will be deleted after being obtained.
@ -678,12 +690,13 @@ void RsGxsNetService::syncGrpStatistics()
for(std::map<RsGxsGroupId,RsGxsGrpMetaData*>::const_iterator it(grpMeta.begin());it!=grpMeta.end();++it)
{
const RsGxsGrpConfig& rec = mServerGrpConfigMap[it->first] ;
const RsGxsGrpConfig& rec = locked_getGrpConfig(it->first) ;
#ifdef NXS_NET_DEBUG_6
GXSNETDEBUG__G(it->first) << " group " << it->first ;
#endif
if(rec.update_TS + GROUP_STATS_UPDATE_DELAY < now && rec.suppliers.ids.size() > 0)
if(rec.statistics_update_TS + GROUP_STATS_UPDATE_DELAY < now && rec.suppliers.ids.size() > 0)
{
#ifdef NXS_NET_DEBUG_6
GXSNETDEBUG__G(it->first) << " needs update. Randomly asking to some friends" << std::endl;
@ -783,7 +796,10 @@ void RsGxsNetService::handleRecvSyncGrpStatistics(RsNxsSyncGrpStatsItem *grs)
grs_resp->grpId = grs->grpId;
grs_resp->PeerId(grs->PeerId()) ;
grs_resp->last_post_TS = 0 ;
grs_resp->last_post_TS = grpMeta->mPublishTs ; // This is not zero, and necessarily older than any message in the group up to clock precision.
// This allows us to use 0 as "uninitialized" proof. If the group meta has been changed, this time
// will be more recent than some messages. This shouldn't be a problem, since this value can only
// be used to discard groups that are not used.
for(uint32_t i=0;i<vec.size();++i)
{
@ -804,14 +820,16 @@ void RsGxsNetService::handleRecvSyncGrpStatistics(RsNxsSyncGrpStatsItem *grs)
GXSNETDEBUG_PG(grs->PeerId(),grs->grpId) << "Received Grp update stats item from peer " << grs->PeerId() << " for group " << grs->grpId << ", reporting " << grs->number_of_posts << " posts." << std::endl;
#endif
RS_STACK_MUTEX(mNxsMutex) ;
RsGxsGrpConfig& rec(mServerGrpConfigMap[grs->grpId]) ;
RsGxsGrpConfig& rec(locked_getGrpConfig(grs->grpId)) ;
uint32_t old_count = rec.max_visible_count ;
uint32_t old_suppliers_count = rec.suppliers.ids.size() ;
rec.suppliers.ids.insert(grs->PeerId()) ;
rec.max_visible_count = std::max(rec.max_visible_count,grs->number_of_posts) ;
rec.update_TS = time(NULL) ;
rec.statistics_update_TS = time(NULL) ;
rec.last_group_modification_TS = grs->last_post_TS;
if (old_count != rec.max_visible_count || old_suppliers_count != rec.suppliers.ids.size())
mNewStatsToNotify.insert(grs->grpId) ;
@ -1419,7 +1437,7 @@ bool RsGxsNetService::loadList(std::list<RsItem *> &load)
// the update time stamp is randomised so as not to ask all friends at once about group statistics.
it->second.update_TS = now - GROUP_STATS_UPDATE_DELAY + (RSRandom::random_u32()%(GROUP_STATS_UPDATE_DELAY/10)) ;
it->second.statistics_update_TS = now - GROUP_STATS_UPDATE_DELAY + (RSRandom::random_u32()%(GROUP_STATS_UPDATE_DELAY/10)) ;
// Similarly, we remove all suppliers.
// Actual suppliers will come back automatically.
@ -1839,7 +1857,7 @@ void RsGxsNetService::debugDump()
GXSNETDEBUG_PG(it->first,it2->first) << " group " << it2->first << " - last updated at peer (secs ago): " << nice_time_stamp(time(NULL),it2->second.time_stamp) << ". Message count=" << it2->second.message_count << std::endl;
}
GXSNETDEBUG___<< " List of rejected message ids: " << mRejectedMessages.size() << std::endl;
GXSNETDEBUG___<< " List of rejected message ids: " << std::dec << mRejectedMessages.size() << std::endl;
#endif
}
@ -2293,6 +2311,7 @@ bool RsGxsNetService::getGroupNetworkStats(const RsGxsGroupId& gid,RsGroupNetwor
stats.mMaxVisibleCount = it->second.max_visible_count ;
stats.mAllowMsgSync = mAllowMsgSync ;
stats.mGrpAutoSync = mGrpAutoSync ;
stats.mLastGroupModificationTS = it->second.last_group_modification_TS ;
return true ;
}
@ -2681,7 +2700,7 @@ void RsGxsNetService::locked_genReqMsgTransaction(NxsTransaction* tr)
uint32_t mcount = msgItemL.size() ;
RsPeerId pid = msgItemL.front()->PeerId() ;
RsGxsGrpConfig& gnsr(mServerGrpConfigMap[grpId]) ;
RsGxsGrpConfig& gnsr(locked_getGrpConfig(grpId));
std::set<RsPeerId>::size_type oldSuppliersCount = gnsr.suppliers.ids.size();
uint32_t oldVisibleCount = gnsr.max_visible_count;
@ -4055,7 +4074,7 @@ void RsGxsNetService::handleRecvSyncMessage(RsNxsSyncMsgReqItem *item,bool item_
if(grp_is_known || mServerGrpConfigMap.find(item->grpId)!=mServerGrpConfigMap.end())
{
RsGxsGrpConfig & rec(mServerGrpConfigMap[item->grpId]) ; // this creates it if needed. When the grp is unknown (and hashed) this will would create a unused entry
RsGxsGrpConfig& rec(locked_getGrpConfig(item->grpId)); // this creates it if needed. When the grp is unknown (and hashed) this will would create a unused entry
rec.suppliers.ids.insert(peer) ;
}
if(!peer_can_receive_update)
@ -4125,7 +4144,7 @@ void RsGxsNetService::handleRecvSyncMessage(RsNxsSyncMsgReqItem *item,bool item_
time_t now = time(NULL) ;
uint32_t max_send_delay = mServerGrpConfigMap[item->grpId].msg_req_delay; // we should use "sync" but there's only one variable used in the GUI: the req one.
uint32_t max_send_delay = locked_getGrpConfig(item->grpId).msg_req_delay; // we should use "sync" but there's only one variable used in the GUI: the req one.
if(canSendMsgIds(msgMetas, *grpMeta, peer, should_encrypt_to_this_circle_id))
{
@ -4414,7 +4433,7 @@ bool RsGxsNetService::checkPermissionsForFriendGroup(const RsPeerId& sslId,const
void RsGxsNetService::pauseSynchronisation(bool /* enabled */)
{
std::cerr << "(EE) RsGxsNetService::pauseSynchronisation() called, but not implemented." << std::endl;
}
void RsGxsNetService::setSyncAge(const RsGxsGroupId &grpId, uint32_t age_in_secs)
@ -4423,7 +4442,7 @@ void RsGxsNetService::setSyncAge(const RsGxsGroupId &grpId, uint32_t age_in_secs
locked_checkDelay(age_in_secs) ;
RsGxsGrpConfig& conf(mServerGrpConfigMap[grpId]) ;
RsGxsGrpConfig& conf(locked_getGrpConfig(grpId));
if(conf.msg_req_delay != age_in_secs)
{
@ -4441,7 +4460,7 @@ void RsGxsNetService::setKeepAge(const RsGxsGroupId &grpId, uint32_t age_in_secs
locked_checkDelay(age_in_secs) ;
RsGxsGrpConfig& conf(mServerGrpConfigMap[grpId]) ;
RsGxsGrpConfig& conf(locked_getGrpConfig(grpId));
if(conf.msg_keep_delay != age_in_secs)
{
@ -4450,27 +4469,39 @@ void RsGxsNetService::setKeepAge(const RsGxsGroupId &grpId, uint32_t age_in_secs
}
}
RsGxsGrpConfig& RsGxsNetService::locked_getGrpConfig(const RsGxsGroupId& grp_id)
{
GrpConfigMap::iterator it = mServerGrpConfigMap.find(grp_id);
if(it == mServerGrpConfigMap.end())
{
RsGxsGrpConfig& conf(mServerGrpConfigMap[grp_id]) ;
conf.msg_keep_delay = mDefaultMsgStorePeriod;
conf.msg_send_delay = mDefaultMsgSyncPeriod;
conf.msg_req_delay = mDefaultMsgSyncPeriod;
conf.max_visible_count = 0 ;
conf.statistics_update_TS = 0 ;
conf.last_group_modification_TS = 0 ;
return conf ;
}
else
return it->second;
}
uint32_t RsGxsNetService::getSyncAge(const RsGxsGroupId& grpId)
{
RS_STACK_MUTEX(mNxsMutex) ;
GrpConfigMap::const_iterator it = mServerGrpConfigMap.find(grpId) ;
if(it == mServerGrpConfigMap.end())
return RS_GXS_DEFAULT_MSG_REQ_PERIOD ;
else
return it->second.msg_req_delay ;
return locked_getGrpConfig(grpId).msg_req_delay ;
}
uint32_t RsGxsNetService::getKeepAge(const RsGxsGroupId& grpId,uint32_t default_value)
uint32_t RsGxsNetService::getKeepAge(const RsGxsGroupId& grpId)
{
RS_STACK_MUTEX(mNxsMutex) ;
GrpConfigMap::const_iterator it = mServerGrpConfigMap.find(grpId) ;
if(it == mServerGrpConfigMap.end())
return default_value ;
else
return it->second.msg_keep_delay ;
return locked_getGrpConfig(grpId).msg_keep_delay ;
}
int RsGxsNetService::requestGrp(const std::list<RsGxsGroupId>& grpId, const RsPeerId& peerId)
@ -4773,6 +4804,8 @@ bool RsGxsNetService::removeGroups(const std::list<RsGxsGroupId>& groups)
GXSNETDEBUG__G(*git) << " deleting info for group " << *git << std::endl;
#endif
// Here we do not use locked_getGrpConfig() because we dont want the entry to be created if it doesnot already exist.
GrpConfigMap::iterator it = mServerGrpConfigMap.find(*git) ;
if(it != mServerGrpConfigMap.end())

View File

@ -88,18 +88,21 @@ public:
* arrive
*/
RsGxsNetService(uint16_t servType, RsGeneralDataService *gds,
RsNxsNetMgr *netMgr,
RsNxsObserver *nxsObs, // used to be = NULL.
const RsServiceInfo serviceInfo,
RsGixsReputation* reputations = NULL, RsGcxs* circles = NULL, RsGixs *gixs=NULL,
PgpAuxUtils *pgpUtils = NULL,
bool grpAutoSync = true, bool msgAutoSync = true);
RsNxsNetMgr *netMgr,
RsNxsObserver *nxsObs, // used to be = NULL.
const RsServiceInfo serviceInfo,
RsGixsReputation* reputations = NULL, RsGcxs* circles = NULL, RsGixs *gixs=NULL,
PgpAuxUtils *pgpUtils = NULL,
bool grpAutoSync = true, bool msgAutoSync = true,
uint32_t default_store_period = RS_GXS_DEFAULT_MSG_STORE_PERIOD,
uint32_t default_sync_period = RS_GXS_DEFAULT_MSG_REQ_PERIOD);
virtual ~RsGxsNetService();
virtual RsServiceInfo getServiceInfo() { return mServiceInfo; }
virtual void getItemNames(std::map<uint8_t,std::string>& names) const ;
public:
@ -111,9 +114,13 @@ public:
virtual void setKeepAge(const RsGxsGroupId& grpId,uint32_t age_in_secs);
virtual uint32_t getSyncAge(const RsGxsGroupId& id);
virtual uint32_t getKeepAge(const RsGxsGroupId& id,uint32_t default_value);
virtual uint32_t getKeepAge(const RsGxsGroupId& id);
virtual uint32_t getDefaultSyncAge() { return RS_GXS_DEFAULT_MSG_REQ_PERIOD ; }
virtual uint32_t getDefaultSyncAge() { return mDefaultMsgSyncPeriod ; }
virtual uint32_t getDefaultKeepAge() { return mDefaultMsgStorePeriod ; }
virtual void setDefaultKeepAge(uint32_t t) { mDefaultMsgStorePeriod = t ; }
virtual void setDefaultSyncAge(uint32_t t) { mDefaultMsgSyncPeriod = t ; }
/*!
* pauses synchronisation of subscribed groups and request for group id
@ -413,6 +420,7 @@ private:
static RsGxsGroupId hashGrpId(const RsGxsGroupId& gid,const RsPeerId& pid) ;
RsGxsGrpConfig& locked_getGrpConfig(const RsGxsGroupId& grp_id);
private:
typedef std::vector<RsNxsGrp*> GrpFragments;
@ -573,6 +581,9 @@ private:
std::set<RsGxsGroupId> mNewPublishKeysToNotify ;
void debugDump();
uint32_t mDefaultMsgStorePeriod ;
uint32_t mDefaultMsgSyncPeriod ;
};
#endif // RSGXSNETSERVICE_H

View File

@ -35,7 +35,7 @@ static const uint32_t MAX_GXS_IDS_REQUESTS_NET = 10 ; // max number of reques
//#define DEBUG_GXSUTIL 1
#define GXSUTIL_DEBUG() std::cerr << time(NULL) << " : GXS_UTIL : " << __FUNCTION__ << " : "
#define GXSUTIL_DEBUG() std::cerr << "[" << time(NULL) << "] : GXS_UTIL : " << __FUNCTION__ << " : "
RsGxsMessageCleanUp::RsGxsMessageCleanUp(RsGeneralDataService* const dataService, RsGenExchange *genex, uint32_t chunkSize)
: mDs(dataService), mGenExchangeClient(genex), CHUNK_SIZE(chunkSize)
@ -57,7 +57,8 @@ bool RsGxsMessageCleanUp::clean()
time_t now = time(NULL);
#ifdef DEBUG_GXSUTIL
GXSUTIL_DEBUG() << " Cleaning up groups in service" << std::hex << mGenExchangeClient->serviceType() << std::dec << std::endl;
uint16_t service_type = mGenExchangeClient->serviceType() ;
GXSUTIL_DEBUG() << " Cleaning up groups in service " << std::hex << service_type << std::dec << std::endl;
#endif
while(!mGrpMeta.empty())
{
@ -97,8 +98,10 @@ bool RsGxsMessageCleanUp::clean()
{
RsGxsMsgMetaData* meta = metaV[i];
bool have_kids = (messages_with_kids.find(meta->mMsgId)!=messages_with_kids.end());
// check if expired
bool remove = store_period > 0 && ((meta->mPublishTs + store_period) < now) && (messages_with_kids.find(meta->mMsgId)==messages_with_kids.end());
bool remove = store_period > 0 && ((meta->mPublishTs + store_period) < now) && !have_kids;
// check client does not want the message kept regardless of age
remove &= !(meta->mMsgStatus & GXS_SERV::GXS_MSG_STATUS_KEEP);
@ -107,12 +110,18 @@ bool RsGxsMessageCleanUp::clean()
remove = remove || (grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_NOT_SUBSCRIBED);
remove = remove || !(grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED);
GXSUTIL_DEBUG() << " msg id " << meta->mMsgId << " in grp " << grpId << ": keep_flag=" << bool(meta->mMsgStatus & GXS_SERV::GXS_MSG_STATUS_KEEP)
<< " subscribed: " << bool(grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) << " store_period: " << store_period
<< " kids: " << have_kids << " now - meta->mPublishTs: " << now - meta->mPublishTs ;
if( remove )
{
req[grpId].push_back(meta->mMsgId);
GXSUTIL_DEBUG() << " Scheduling msg id " << meta->mMsgId << " in grp " << grpId << " for removal." << std::endl;
std::cerr << " Scheduling for removal." << std::endl;
}
else
std::cerr << std::endl;
delete meta;
}
@ -136,6 +145,9 @@ RsGxsIntegrityCheck::RsGxsIntegrityCheck(RsGeneralDataService* const dataService
void RsGxsIntegrityCheck::run()
{
check();
RsStackMutex stack(mIntegrityMutex);
mDone = true;
}
bool RsGxsIntegrityCheck::check()
@ -286,71 +298,72 @@ bool RsGxsIntegrityCheck::check()
mDs->removeMsgs(msgsToDel);
RsStackMutex stack(mIntegrityMutex);
mDone = true;
{
RsStackMutex stack(mIntegrityMutex);
std::vector<RsGxsGroupId>::iterator grpIt;
for(grpIt = grpsToDel.begin(); grpIt != grpsToDel.end(); ++grpIt)
{
mDeletedGrps.push_back(*grpIt);
}
mDeletedMsgs = msgsToDel;
std::vector<RsGxsGroupId>::iterator grpIt;
for(grpIt = grpsToDel.begin(); grpIt != grpsToDel.end(); ++grpIt)
{
mDeletedGrps.push_back(*grpIt);
}
mDeletedMsgs = msgsToDel;
#ifdef DEBUG_GXSUTIL
GXSUTIL_DEBUG() << "At end of pass, this is the list used GXS ids: " << std::endl;
GXSUTIL_DEBUG() << " requesting them to GXS identity service to enforce loading." << std::endl;
GXSUTIL_DEBUG() << "At end of pass, this is the list used GXS ids: " << std::endl;
GXSUTIL_DEBUG() << " requesting them to GXS identity service to enforce loading." << std::endl;
#endif
std::list<RsPeerId> connected_friends ;
rsPeers->getOnlineList(connected_friends) ;
std::list<RsPeerId> connected_friends ;
rsPeers->getOnlineList(connected_friends) ;
std::vector<std::pair<RsGxsId,RsIdentityUsage> > gxs_ids ;
std::vector<std::pair<RsGxsId,RsIdentityUsage> > gxs_ids ;
for(std::map<RsGxsId,RsIdentityUsage>::const_iterator it(used_gxs_ids.begin());it!=used_gxs_ids.end();++it)
{
gxs_ids.push_back(*it) ;
for(std::map<RsGxsId,RsIdentityUsage>::const_iterator it(used_gxs_ids.begin());it!=used_gxs_ids.end();++it)
{
gxs_ids.push_back(*it) ;
#ifdef DEBUG_GXSUTIL
GXSUTIL_DEBUG() << " " << *it << std::endl;
GXSUTIL_DEBUG() << " " << it->first << std::endl;
#endif
}
uint32_t nb_requested_not_in_cache = 0;
}
uint32_t nb_requested_not_in_cache = 0;
#ifdef DEBUG_GXSUTIL
GXSUTIL_DEBUG() << " issuing random get on friends for non existing IDs" << std::endl;
GXSUTIL_DEBUG() << " issuing random get on friends for non existing IDs" << std::endl;
#endif
// now request a cache update for them, which triggers downloading from friends, if missing.
// now request a cache update for them, which triggers downloading from friends, if missing.
for(;nb_requested_not_in_cache<MAX_GXS_IDS_REQUESTS_NET && !gxs_ids.empty();)
{
uint32_t n = RSRandom::random_u32() % gxs_ids.size() ;
for(;nb_requested_not_in_cache<MAX_GXS_IDS_REQUESTS_NET && !gxs_ids.empty();)
{
uint32_t n = RSRandom::random_u32() % gxs_ids.size() ;
#ifdef DEBUG_GXSUTIL
GXSUTIL_DEBUG() << " requesting ID " << gxs_ids[n] ;
GXSUTIL_DEBUG() << " requesting ID " << gxs_ids[n].first ;
#endif
if(!mGixs->haveKey(gxs_ids[n].first)) // checks if we have it already in the cache (conservative way to ensure that we atually have it)
{
mGixs->requestKey(gxs_ids[n].first,connected_friends,gxs_ids[n].second);
if(!mGixs->haveKey(gxs_ids[n].first)) // checks if we have it already in the cache (conservative way to ensure that we atually have it)
{
mGixs->requestKey(gxs_ids[n].first,connected_friends,gxs_ids[n].second);
++nb_requested_not_in_cache ;
++nb_requested_not_in_cache ;
#ifdef DEBUG_GXSUTIL
GXSUTIL_DEBUG() << " ... from cache/net" << std::endl;
GXSUTIL_DEBUG() << " ... from cache/net" << std::endl;
#endif
}
else
{
}
else
{
#ifdef DEBUG_GXSUTIL
GXSUTIL_DEBUG() << " ... already in cache" << std::endl;
GXSUTIL_DEBUG() << " ... already in cache" << std::endl;
#endif
}
mGixs->timeStampKey(gxs_ids[n].first,gxs_ids[n].second);
}
mGixs->timeStampKey(gxs_ids[n].first,gxs_ids[n].second);
gxs_ids[n] = gxs_ids[gxs_ids.size()-1] ;
gxs_ids.pop_back() ;
}
gxs_ids[n] = gxs_ids[gxs_ids.size()-1] ;
gxs_ids.pop_back() ;
}
#ifdef DEBUG_GXSUTIL
GXSUTIL_DEBUG() << " total actual cache requests: "<< nb_requested_not_in_cache << std::endl;
GXSUTIL_DEBUG() << " total actual cache requests: "<< nb_requested_not_in_cache << std::endl;
#endif
}
return true;
}

View File

@ -73,9 +73,13 @@ public:
virtual void setKeepAge(const RsGxsGroupId& id,uint32_t age_in_secs) =0;
virtual uint32_t getSyncAge(const RsGxsGroupId& id) =0;
virtual uint32_t getKeepAge(const RsGxsGroupId& id,uint32_t default_value) =0;
virtual uint32_t getKeepAge(const RsGxsGroupId& id) =0;
virtual void setDefaultKeepAge(uint32_t t) =0;
virtual void setDefaultSyncAge(uint32_t t) =0;
virtual uint32_t getDefaultSyncAge() =0;
virtual uint32_t getDefaultKeepAge() =0;
/*!
* Initiates a search through the network

View File

@ -20,23 +20,30 @@
#include "gxstrans/p3gxstrans.h"
#include "util/stacktrace.h"
//#define DEBUG_GXSTRANS 1
typedef unsigned int uint;
RsGxsTrans *rsGxsTrans = NULL ;
const uint32_t p3GxsTrans::MAX_DELAY_BETWEEN_CLEANUPS = 900; // every 15 mins. Could be less.
p3GxsTrans::~p3GxsTrans()
{
p3Config::saveConfiguration();
{
RS_STACK_MUTEX(mIngoingMutex);
for ( auto& kv : mIngoingQueue ) delete kv.second;
for ( auto& kv : mIncomingQueue) delete kv.second;
}
}
bool p3GxsTrans::getStatistics(GxsTransStatistics& stats)
{
stats.prefered_group_id = mPreferredGroupId;
{
RS_STACK_MUTEX(mDataMutex);
stats.prefered_group_id = mPreferredGroupId;
}
stats.outgoing_records.clear();
{
@ -48,8 +55,8 @@ bool p3GxsTrans::getStatistics(GxsTransStatistics& stats)
RsGxsTransOutgoingRecord rec ;
rec.status = pr.status ;
rec.send_TS = pr.mailItem.meta.mPublishTs ;
rec.group_id = pr.mailItem.meta.mGroupId ;
rec.send_TS = pr.sent_ts ;
rec.group_id = pr.group_id ;
rec.trans_id = pr.mailItem.mailId ;
rec.recipient = pr.recipient ;
rec.data_size = pr.mailData.size();
@ -69,7 +76,9 @@ bool p3GxsTrans::sendData( RsGxsTransId& mailId,
const uint8_t* data, uint32_t size,
RsGxsTransEncryptionMode cm )
{
#ifdef DEBUG_GXSTRANS
std::cout << "p3GxsTrans::sendEmail(...)" << std::endl;
#endif
if(!mIdService.isOwnId(own_gxsid))
{
@ -89,8 +98,7 @@ bool p3GxsTrans::sendData( RsGxsTransId& mailId,
OutgoingRecord pr( recipient, service, data, size );
pr.mailItem.clear();
pr.mailItem.meta.mAuthorId = own_gxsid;
pr.mailItem.meta.mMsgId.clear();
pr.author = own_gxsid; //pr.mailItem.meta.mAuthorId = own_gxsid;
pr.mailItem.cryptoType = cm;
pr.mailItem.mailId = RSRandom::random_u64();
@ -100,6 +108,8 @@ bool p3GxsTrans::sendData( RsGxsTransId& mailId,
}
mailId = pr.mailItem.mailId;
IndicateConfigChanged(); // This causes the saving of the message after all data has been filled in.
return true;
}
@ -124,15 +134,42 @@ void p3GxsTrans::registerGxsTransClient(
void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type)
{
std::cout << "p3GxsTrans::handleResponse(" << token << ", " << req_type
<< ")" << std::endl;
#ifdef DEBUG_GXSTRANS
std::cout << "p3GxsTrans::handleResponse(" << token << ", " << req_type << ")" << std::endl;
#endif
bool changed = false ;
switch (req_type)
{
case GROUPS_LIST:
{
#ifdef DEBUG_GXSTRANS
std::cerr << " Reviewing available groups. " << std::endl;
#endif
std::vector<RsGxsGrpItem*> groups;
getGroupData(token, groups);
// First recompute the prefered group Id.
{
RS_STACK_MUTEX(mDataMutex);
for( auto grp : groups )
{
locked_supersedePreferredGroup(grp->meta.mGroupId);
if(RsGenExchange::getStoragePeriod(grp->meta.mGroupId) != GXS_STORAGE_PERIOD)
{
std::cerr << "(WW) forcing storage period in GxsTrans group " << grp->meta.mGroupId << " to " << GXS_STORAGE_PERIOD << " seconds. Value was " << RsGenExchange::getStoragePeriod(grp->meta.mGroupId) << std::endl;
RsGenExchange::setStoragePeriod(grp->meta.mGroupId,GXS_STORAGE_PERIOD) ;
}
}
}
#ifdef DEBUG_GXSTRANS
std::cerr << " computed preferred group id: " << mPreferredGroupId << std::endl;
#endif
for( auto grp : groups )
{
/* For each group check if it is better candidate then
@ -145,18 +182,29 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type)
const RsGroupMetaData& meta = grp->meta;
bool subscribed = IS_GROUP_SUBSCRIBED(meta.mSubscribeFlags);
bool old = olderThen( meta.mLastPost,
UNUSED_GROUP_UNSUBSCRIBE_INTERVAL );
bool supersede = supersedePreferredGroup(meta.mGroupId);
// if mLastPost is 0, then the group is not subscribed, so it only has impact on shouldSubscribe. In any case, a group
// with no information shouldn't be subscribed, so the olderThen() test is still valid in the case mLastPost=0.
bool old = olderThen( meta.mLastPost, UNUSED_GROUP_UNSUBSCRIBE_INTERVAL );
uint32_t token;
bool shoudlSubscribe = !subscribed && ( !old || supersede );
bool shoudlUnSubscribe = subscribed && old
&& meta.mGroupId != mPreferredGroupId;
bool shouldSubscribe = false ;
bool shouldUnSubscribe = false ;
{
RS_STACK_MUTEX(mDataMutex);
if(shoudlSubscribe)
shouldSubscribe = (!subscribed) && ((!old)|| meta.mGroupId == mPreferredGroupId );
shouldUnSubscribe = ( subscribed) && old && meta.mGroupId != mPreferredGroupId;
}
#ifdef DEBUG_GXSTRANS
std::cout << " group " << grp->meta.mGroupId << ", subscribed: " << subscribed << " last post: " << meta.mLastPost << " should subscribe: "<< shouldSubscribe
<< ", should unsubscribe: " << shouldUnSubscribe << std::endl;
#endif
if(shouldSubscribe)
RsGenExchange::subscribeToGroup(token, meta.mGroupId, true);
else if(shoudlUnSubscribe)
else if(shouldUnSubscribe)
RsGenExchange::subscribeToGroup(token, meta.mGroupId, false);
#ifdef GXS_MAIL_GRP_DEBUG
@ -178,7 +226,14 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type)
delete grp;
}
if(mPreferredGroupId.isNull())
bool have_preferred_group = false ;
{
RS_STACK_MUTEX(mDataMutex);
have_preferred_group = !mPreferredGroupId.isNull();
}
if(!have_preferred_group)
{
/* This is true only at first run when we haven't received mail
* distribuition groups from friends
@ -186,8 +241,10 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type)
* avoid to create yet another never used mail distribution group.
*/
#ifdef DEBUG_GXSTRANS
std::cerr << "p3GxsTrans::handleResponse(...) preferredGroupId.isNu"
<< "ll() let's create a new group." << std::endl;
#endif
uint32_t token;
publishGroup(token, new RsGxsTransGroupItem());
queueRequest(token, GROUP_CREATE);
@ -197,15 +254,21 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type)
}
case GROUP_CREATE:
{
#ifdef DEBUG_GXSTRANS
std::cerr << "p3GxsTrans::handleResponse(...) GROUP_CREATE" << std::endl;
#endif
RsGxsGroupId grpId;
acknowledgeTokenGrp(token, grpId);
supersedePreferredGroup(grpId);
RS_STACK_MUTEX(mDataMutex);
locked_supersedePreferredGroup(grpId);
break;
}
case MAILS_UPDATE:
{
#ifdef DEBUG_GXSTRANS
std::cout << "p3GxsTrans::handleResponse(...) MAILS_UPDATE" << std::endl;
#endif
typedef std::map<RsGxsGroupId, std::vector<RsGxsMsgItem*> > GxsMsgDataMap;
GxsMsgDataMap gpMsgMap;
getMsgData(token, gpMsgMap);
@ -222,12 +285,14 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type)
case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL:
case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT:
{
RsGxsTransBaseItem* mb =
dynamic_cast<RsGxsTransBaseItem*>(*mIt);
RsGxsTransBaseMsgItem* mb = dynamic_cast<RsGxsTransBaseMsgItem*>(*mIt);
if(mb)
{
RS_STACK_MUTEX(mIngoingMutex);
mIngoingQueue.insert(inMap::value_type(mb->mailId, mb));
mIncomingQueue.insert(inMap::value_type(mb->mailId,mb));
changed = true ;
}
else
std::cerr << "p3GxsTrans::handleResponse(...) "
@ -253,15 +318,52 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type)
<< req_type << std::endl;
break;
}
if(changed)
IndicateConfigChanged();
}
void p3GxsTrans::GxsTransIntegrityCleanupThread::getPerUserStatistics(std::map<RsGxsId,MsgSizeCount>& m)
{
RS_STACK_MUTEX(mMtx) ;
m = total_message_size_and_count ;
}
void p3GxsTrans::GxsTransIntegrityCleanupThread::getMessagesToDelete(GxsMsgReq& m)
{
RS_STACK_MUTEX(mMtx) ;
m = mMsgToDel ;
mMsgToDel.clear();
}
// This method does two things:
// 1 - cleaning up old messages and messages for which an ACK has been received.
// 2 - building per user statistics across groups. This is important because it allows to mitigate the excess of
// messages, which might be due to spam.
//
// Note: the anti-spam system is disabled the level of GXS, because we want to allow to send anonymous messages
// between identities that might not have a reputation yet. Still, messages from identities with a bad reputation
// are still deleted by GXS.
//
// The group limits are enforced according to the following rules:
// * a temporal sliding window is computed for each identity and the number of messages signed by this identity is counted
// *
//
//
// Deleted messages are notified to the RsGxsNetService part which keeps a list of delete messages so as not to request them again
// during the same session. This allows to safely delete messages while avoiding re-synchronisation from friend nodes.
void p3GxsTrans::GxsTransIntegrityCleanupThread::run()
{
// first take out all the groups
std::map<RsGxsGroupId, RsNxsGrp*> grp;
mDs->retrieveNxsGrps(grp, true, true);
#ifdef DEBUG_GXSTRANS
std::cerr << "GxsTransIntegrityCleanupThread::run()" << std::endl;
#endif
// compute hash and compare to stored value, if it fails then simply add it
// to list
@ -279,6 +381,8 @@ void p3GxsTrans::GxsTransIntegrityCleanupThread::run()
// now messages
std::map<RsGxsId,MsgSizeCount> totalMessageSizeAndCount;
std::map<RsGxsTransId,std::pair<RsGxsGroupId,RsGxsMessageId> > stored_msgs ;
std::list<RsGxsTransId> received_msgs ;
@ -289,6 +393,9 @@ void p3GxsTrans::GxsTransIntegrityCleanupThread::run()
{
std::vector<RsNxsMsg*>& msgV = mit->second;
std::vector<RsNxsMsg*>::iterator vit = msgV.begin();
#ifdef DEBUG_GXSTRANS
std::cerr << "Group " << mit->first << ": " << std::endl;
#endif
for(; vit != msgV.end(); ++vit)
{
@ -304,27 +411,44 @@ void p3GxsTrans::GxsTransIntegrityCleanupThread::run()
std::cerr << " Unrecocognised item type!" << std::endl;
else if(NULL != (mitem = dynamic_cast<RsGxsTransMailItem*>(item)))
{
std::cerr << " " << msg->metaData->mMsgId << ": Mail data with ID " << std::hex << mitem->mailId << std::dec << " from " << msg->metaData->mAuthorId << " size: " << msg->msg.bin_len << std::endl;
#ifdef DEBUG_GXSTRANS
std::cerr << " " << msg->metaData->mMsgId << ": Mail data with ID " << std::hex << std::setfill('0') << std::setw(16) << mitem->mailId << std::dec << " from " << msg->metaData->mAuthorId << " size: " << msg->msg.bin_len << std::endl;
#endif
stored_msgs[mitem->mailId] = std::make_pair(msg->metaData->mGroupId,msg->metaData->mMsgId) ;
}
else if(NULL != (pitem = dynamic_cast<RsGxsTransPresignedReceipt*>(item)))
{
#ifdef DEBUG_GXSTRANS
std::cerr << " " << msg->metaData->mMsgId << ": Signed rcpt of ID " << std::hex << pitem->mailId << std::dec << " from " << msg->metaData->mAuthorId << " size: " << msg->msg.bin_len << std::endl;
#endif
received_msgs.push_back(pitem->mailId) ;
}
else
std::cerr << " Unknown item type!" << std::endl;
totalMessageSizeAndCount[msg->metaData->mAuthorId].size += msg->msg.bin_len ;
totalMessageSizeAndCount[msg->metaData->mAuthorId].count++;
delete msg;
if(item != NULL)
delete item ;
}
}
// From the collected information, build a list of group messages to delete.
GxsMsgReq msgsToDel ;
#ifdef DEBUG_GXSTRANS
std::cerr << "Msg removal report:" << std::endl;
std::cerr << " Per user size and count: " << std::endl;
for(std::map<RsGxsId,MsgSizeCount>::const_iterator it(totalMessageSizeAndCount.begin());it!=totalMessageSizeAndCount.end();++it)
std::cerr << " " << it->first << ": " << it->second.count << " messages, for a total size of " << it->second.size << " bytes." << std::endl;
#endif
for(std::list<RsGxsTransId>::const_iterator it(received_msgs.begin());it!=received_msgs.end();++it)
{
std::map<RsGxsTransId,std::pair<RsGxsGroupId,RsGxsMessageId> >::const_iterator it2 = stored_msgs.find(*it) ;
@ -333,21 +457,33 @@ void p3GxsTrans::GxsTransIntegrityCleanupThread::run()
{
msgsToDel[it2->second.first].push_back(it2->second.second);
#ifdef DEBUG_GXSTRANS
std::cerr << " scheduling msg " << std::hex << it2->second.first << "," << it2->second.second << " for deletion." << std::endl;
#endif
}
}
mDs->removeMsgs(msgsToDel);
RS_STACK_MUTEX(mMtx) ;
mMsgToDel = msgsToDel ;
total_message_size_and_count = totalMessageSizeAndCount;
mDone = true;
}
bool p3GxsTrans::GxsTransIntegrityCleanupThread::isDone()
{
RS_STACK_MUTEX(mMtx) ;
return mDone ;
}
void p3GxsTrans::service_tick()
{
GxsTokenQueue::checkRequests();
time_t now = time(NULL);
bool changed = false ;
if(mLastMsgCleanup + MAX_DELAY_BETWEEN_CLEANUPS < now)
{
RS_STACK_MUTEX(mPerUserStatsMutex);
if(!mCleanupThread)
mCleanupThread = new GxsTransIntegrityCleanupThread(getDataStore());
@ -355,23 +491,64 @@ void p3GxsTrans::service_tick()
std::cerr << "Cleanup thread is already running. Not running it again!" << std::endl;
else
{
#ifdef DEBUG_GXSTRANS
std::cerr << "Starting GxsIntegrity cleanup thread." << std::endl;
#endif
mCleanupThread->start() ;
mLastMsgCleanup = now ;
}
// This forces to review all groups, and decide to subscribe or not to each of them.
requestGroupsData();
}
// now grab collected messages to delete
if(mCleanupThread != NULL && mCleanupThread->isDone())
{
RS_STACK_MUTEX(mPerUserStatsMutex);
GxsMsgReq msgToDel ;
mCleanupThread->getMessagesToDelete(msgToDel) ;
if(!msgToDel.empty())
{
#ifdef DEBUG_GXSTRANS
std::cerr << "p3GxsTrans::service_tick(): deleting messages." << std::endl;
#endif
uint32_t token ;
deleteMsgs(token,msgToDel);
}
mCleanupThread->getPerUserStatistics(per_user_statistics) ;
#ifdef DEBUG_GXSTRANS
std::cerr << "p3GxsTrans: Got new set of per user statistics:"<< std::endl;
for(std::map<RsGxsId,MsgSizeCount>::const_iterator it(per_user_statistics.begin());it!=per_user_statistics.end();++it)
std::cerr << " " << it->first << ": " << it->second.count << " " << it->second.size << std::endl;
#endif
delete mCleanupThread;
mCleanupThread=NULL ;
}
{
RS_STACK_MUTEX(mOutgoingMutex);
for ( auto it = mOutgoingQueue.begin(); it != mOutgoingQueue.end(); )
{
OutgoingRecord& pr(it->second);
GxsTransSendStatus oldStatus = pr.status;
processOutgoingRecord(pr);
locked_processOutgoingRecord(pr);
if (oldStatus != pr.status) notifyClientService(pr);
if( pr.status >= GxsTransSendStatus::RECEIPT_RECEIVED )
{
it = mOutgoingQueue.erase(it);
changed = true ;
}
else ++it;
}
}
@ -379,15 +556,14 @@ void p3GxsTrans::service_tick()
{
RS_STACK_MUTEX(mIngoingMutex);
for( auto it = mIngoingQueue.begin(); it != mIngoingQueue.end(); )
for( auto it = mIncomingQueue.begin(); it != mIncomingQueue.end(); )
{
switch(static_cast<GxsTransItemsSubtypes>(
it->second->PacketSubType()))
switch(static_cast<GxsTransItemsSubtypes>( it->second->PacketSubType()))
{
case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL:
{
RsGxsTransMailItem* msg =
dynamic_cast<RsGxsTransMailItem*>(it->second);
RsGxsTransMailItem* msg = dynamic_cast<RsGxsTransMailItem*>(it->second);
if(!msg)
{
std::cerr << "p3GxsTrans::service_tick() (EE) "
@ -397,6 +573,7 @@ void p3GxsTrans::service_tick()
}
else
{
#ifdef DEBUG_GXSTRANS
std::cout << "p3GxsTrans::service_tick() "
<< "GXS_MAIL_SUBTYPE_MAIL handling: "
<< msg->meta.mMsgId
@ -406,14 +583,15 @@ void p3GxsTrans::service_tick()
<< " mailId: "<< msg->mailId
<< " payload.size(): " << msg->payload.size()
<< std::endl;
#endif
handleEncryptedMail(msg);
}
break;
}
case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT:
{
RsGxsTransPresignedReceipt* rcpt =
dynamic_cast<RsGxsTransPresignedReceipt*>(it->second);
RsGxsTransPresignedReceipt* rcpt = dynamic_cast<RsGxsTransPresignedReceipt*>(it->second);
if(!rcpt)
{
std::cerr << "p3GxsTrans::service_tick() (EE) "
@ -443,22 +621,31 @@ void p3GxsTrans::service_tick()
break;
}
delete it->second; it = mIngoingQueue.erase(it);
delete it->second ;
it = mIncomingQueue.erase(it);
changed = true ;
}
}
if(changed)
IndicateConfigChanged();
}
RsGenExchange::ServiceCreate_Return p3GxsTrans::service_CreateGroup(
RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& /*keySet*/ )
{
#ifdef DEBUG_GXSTRANS
std::cout << "p3GxsTrans::service_CreateGroup(...) "
<< grpItem->meta.mGroupId << std::endl;
#endif
return SERVICE_CREATE_SUCCESS;
}
void p3GxsTrans::notifyChanges(std::vector<RsGxsNotify*>& changes)
{
#ifdef DEBUG_GXSTRANS
std::cout << "p3GxsTrans::notifyChanges(...)" << std::endl;
#endif
for( std::vector<RsGxsNotify*>::const_iterator it = changes.begin();
it != changes.end(); ++it )
{
@ -467,12 +654,16 @@ void p3GxsTrans::notifyChanges(std::vector<RsGxsNotify*>& changes)
if (grpChange)
{
#ifdef DEBUG_GXSTRANS
std::cout << "p3GxsTrans::notifyChanges(...) grpChange" << std::endl;
#endif
requestGroupsData(&(grpChange->mGrpIdList));
}
else if(msgChange)
{
#ifdef DEBUG_GXSTRANS
std::cout << "p3GxsTrans::notifyChanges(...) msgChange" << std::endl;
#endif
uint32_t token;
RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
RsGenExchange::getTokenService()->requestMsgInfo( token, 0xcaca,
@ -488,13 +679,16 @@ void p3GxsTrans::notifyChanges(std::vector<RsGxsNotify*>& changes)
for(itT vit = msgsIds.begin(); vit != msgsIds.end(); ++vit)
{
const RsGxsMessageId& msgId = *vit;
#ifdef DEBUG_GXSTRANS
std::cout << "p3GxsTrans::notifyChanges(...) got "
<< "notification for message " << msgId
<< " in group " << grpId << std::endl;
#endif
}
}
}
}
RsGxsIfaceHelper::receiveChanges(changes);
}
uint32_t p3GxsTrans::AuthenPolicy()
@ -539,7 +733,9 @@ bool p3GxsTrans::requestGroupsData(const std::list<RsGxsGroupId>* groupIds)
bool p3GxsTrans::handleEncryptedMail(const RsGxsTransMailItem* mail)
{
#ifdef DEBUG_GXSTRANS
std::cout << "p3GxsTrans::handleEcryptedMail(...)" << std::endl;
#endif
std::set<RsGxsId> decryptIds;
std::list<RsGxsId> ownIds;
@ -562,8 +758,11 @@ bool p3GxsTrans::handleEncryptedMail(const RsGxsTransMailItem* mail)
uint16_t csri = 0;
uint32_t off = 0;
getRawUInt16(&mail->payload[0], mail->payload.size(), &off, &csri);
#ifdef DEBUG_GXSTRANS
std::cerr << "service: " << csri << " got CLEAR_TEXT mail!"
<< std::endl;
#endif
/* As we cannot verify recipient without encryption, just pass the hint
* as recipient */
return dispatchDecryptedMail( mail->meta.mAuthorId, mail->recipientHint,
@ -602,8 +801,10 @@ bool p3GxsTrans::dispatchDecryptedMail( const RsGxsId& authorId,
const uint8_t* decrypted_data,
uint32_t decrypted_data_size )
{
#ifdef DEBUG_GXSTRANS
std::cout << "p3GxsTrans::dispatchDecryptedMail(, , " << decrypted_data_size
<< ")" << std::endl;
#endif
uint16_t csri = 0;
uint32_t offset = 0;
@ -629,8 +830,10 @@ bool p3GxsTrans::dispatchDecryptedMail( const RsGxsId& authorId,
<< " wrong is happening!" << std::endl;
return false;
}
#ifdef DEBUG_GXSTRANS
std::cout << "p3GxsTrans::dispatchDecryptedMail(...) dispatching receipt "
<< "with: msgId: " << receipt->msgId << std::endl;
#endif
std::vector<RsNxsMsg*> rcct; rcct.push_back(receipt);
RsGenExchange::notifyNewMessages(rcct);
@ -654,7 +857,7 @@ bool p3GxsTrans::dispatchDecryptedMail( const RsGxsId& authorId,
}
}
void p3GxsTrans::processOutgoingRecord(OutgoingRecord& pr)
void p3GxsTrans::locked_processOutgoingRecord(OutgoingRecord& pr)
{
//std::cout << "p3GxsTrans::processRecord(...)" << std::endl;
@ -664,10 +867,12 @@ void p3GxsTrans::processOutgoingRecord(OutgoingRecord& pr)
{
pr.mailItem.saltRecipientHint(pr.recipient);
pr.mailItem.saltRecipientHint(RsGxsId::random());
pr.mailItem.meta.mPublishTs = time(NULL);
pr.sent_ts = time(NULL) ; //pr.mailItem.meta.mPublishTs = time(NULL);
}
case GxsTransSendStatus::PENDING_PREFERRED_GROUP:
{
RS_STACK_MUTEX(mDataMutex);
if(mPreferredGroupId.isNull())
{
requestGroupsData();
@ -675,12 +880,16 @@ void p3GxsTrans::processOutgoingRecord(OutgoingRecord& pr)
break;
}
pr.mailItem.meta.mGroupId = mPreferredGroupId;
pr.group_id = mPreferredGroupId ; //pr.mailItem.meta.mGroupId = mPreferredGroupId;
}
case GxsTransSendStatus::PENDING_RECEIPT_CREATE:
{
RsGxsTransPresignedReceipt grcpt;
grcpt.meta = pr.mailItem.meta;
grcpt.meta.mAuthorId = pr.author ; //grcpt.meta = pr.mailItem.meta;
grcpt.meta.mGroupId = pr.group_id ; //grcpt.meta = pr.mailItem.meta;
grcpt.meta.mMsgId.clear() ;
grcpt.meta.mParentId.clear() ;
grcpt.meta.mOrigMsgId.clear() ;
grcpt.meta.mPublishTs = time(NULL);
grcpt.mailId = pr.mailItem.mailId;
uint32_t grsz = RsGxsTransSerializer().size(&grcpt);
@ -688,12 +897,15 @@ void p3GxsTrans::processOutgoingRecord(OutgoingRecord& pr)
grsrz.resize(grsz);
RsGxsTransSerializer().serialise(&grcpt, &grsrz[0], &grsz);
pr.presignedReceipt.grpId = mPreferredGroupId;
{
RS_STACK_MUTEX(mDataMutex);
pr.presignedReceipt.grpId = mPreferredGroupId;
}
pr.presignedReceipt.metaData = new RsGxsMsgMetaData();
*pr.presignedReceipt.metaData = grcpt.meta;
pr.presignedReceipt.msg.setBinData(&grsrz[0], grsz);
}
case GxsTransSendStatus::PENDING_RECEIPT_SIGNATURE:
case GxsTransSendStatus::PENDING_RECEIPT_SIGNATURE: // (cyril) This step is never actually used.
{
switch (RsGenExchange::createMessage(&pr.presignedReceipt))
{
@ -771,6 +983,7 @@ void p3GxsTrans::processOutgoingRecord(OutgoingRecord& pr)
}
case GxsTransSendStatus::PENDING_PUBLISH:
{
#ifdef DEBUG_GXSTRANS
std::cout << "p3GxsTrans::sendEmail(...) sending mail to: "
<< pr.recipient
<< " with cryptoType: "
@ -779,28 +992,50 @@ void p3GxsTrans::processOutgoingRecord(OutgoingRecord& pr)
<< " receiptId: " << pr.mailItem.mailId
<< " payload size: " << pr.mailItem.payload.size()
<< std::endl;
#endif
RsGxsTransMailItem *mail_item = new RsGxsTransMailItem(pr.mailItem);
// pr.mailItem.meta is *not* serialised. So it is important to not rely on what's in it!
mail_item->meta.mGroupId = pr.group_id ;
mail_item->meta.mAuthorId = pr.author ;
mail_item->meta.mMsgId.clear();
mail_item->meta.mParentId.clear();
mail_item->meta.mOrigMsgId.clear();
uint32_t token;
publishMsg(token, new RsGxsTransMailItem(pr.mailItem));
publishMsg(token, mail_item) ;
pr.status = GxsTransSendStatus::PENDING_RECEIPT_RECEIVE;
IndicateConfigChanged(); // This causes the saving of the message after pr.status has changed.
break;
}
//case GxsTransSendStatus::PENDING_TRANSFER:
case GxsTransSendStatus::PENDING_RECEIPT_RECEIVE:
{
RS_STACK_MUTEX(mIngoingMutex);
auto range = mIngoingQueue.equal_range(pr.mailItem.mailId);
auto range = mIncomingQueue.equal_range(pr.mailItem.mailId);
bool changed = false ;
for( auto it = range.first; it != range.second; ++it)
{
RsGxsTransPresignedReceipt* rt =
dynamic_cast<RsGxsTransPresignedReceipt*>(it->second);
RsGxsTransPresignedReceipt* rt = dynamic_cast<RsGxsTransPresignedReceipt*>(it->second);
if(rt && mIdService.isOwnId(rt->meta.mAuthorId))
{
mIngoingQueue.erase(it); delete rt;
mIncomingQueue.erase(it); delete rt;
pr.status = GxsTransSendStatus::RECEIPT_RECEIVED;
changed = true ;
break;
}
}
if(changed)
IndicateConfigChanged();
// TODO: Resend message if older then treshold
break;
}
@ -851,19 +1086,31 @@ RsSerialiser* p3GxsTrans::setupSerialiser()
bool p3GxsTrans::saveList(bool &cleanup, std::list<RsItem *>& saveList)
{
std::cout << "p3GxsTrans::saveList(...)" << saveList.size() << " "
<< mIngoingQueue.size() << " " << mOutgoingQueue.size()
<< std::endl;
#ifdef DEBUG_GXSTRANS
std::cout << "p3GxsTrans::saveList(...)" << saveList.size() << " " << mIncomingQueue.size() << " " << mOutgoingQueue.size() << std::endl;
#endif
mOutgoingMutex.lock();
mIngoingMutex.lock();
for ( auto& kv : mOutgoingQueue ) saveList.push_back(&kv.second);
for ( auto& kv : mIngoingQueue ) saveList.push_back(kv.second);
for ( auto& kv : mOutgoingQueue )
{
#ifdef DEBUG_GXSTRANS
std::cerr << "Saving outgoing item, ID " << std::hex << std::setfill('0') << std::setw(16) << kv.first << std::dec << "Group id: " << kv.second.group_id << ", TS=" << kv.second.sent_ts << std::endl;
#endif
saveList.push_back(&kv.second);
}
for ( auto& kv : mIncomingQueue )
{
#ifdef DEBUG_GXSTRANS
std::cerr << "Saving incoming item, ID " << std::hex << std::setfill('0') << std::setw(16) << kv.first << std::endl;
#endif
saveList.push_back(kv.second);
}
std::cout << "p3GxsTrans::saveList(...)" << saveList.size() << " "
<< mIngoingQueue.size() << " " << mOutgoingQueue.size()
<< std::endl;
#ifdef DEBUG_GXSTRANS
std::cout << "p3GxsTrans::saveList(...)" << saveList.size() << " " << mIncomingQueue.size() << " " << mOutgoingQueue.size() << std::endl;
#endif
cleanup = false;
return true;
@ -877,9 +1124,11 @@ void p3GxsTrans::saveDone()
bool p3GxsTrans::loadList(std::list<RsItem *>&loadList)
{
#ifdef DEBUG_GXSTRANS
std::cout << "p3GxsTrans::loadList(...) " << loadList.size() << " "
<< mIngoingQueue.size() << " " << mOutgoingQueue.size()
<< mIncomingQueue.size() << " " << mOutgoingQueue.size()
<< std::endl;
#endif
for(auto& v : loadList)
switch(static_cast<GxsTransItemsSubtypes>(v->PacketSubType()))
@ -887,14 +1136,44 @@ bool p3GxsTrans::loadList(std::list<RsItem *>&loadList)
case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL:
case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT:
{
RsGxsTransBaseItem* mi = dynamic_cast<RsGxsTransBaseItem*>(v);
RsGxsTransBaseMsgItem* mi = dynamic_cast<RsGxsTransBaseMsgItem*>(v);
if(mi)
{
RS_STACK_MUTEX(mIngoingMutex);
mIngoingQueue.insert(inMap::value_type(mi->mailId, mi));
mIncomingQueue.insert(inMap::value_type(mi->mailId, mi));
}
break;
}
case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM_deprecated:
{
OutgoingRecord_deprecated* dot = dynamic_cast<OutgoingRecord_deprecated*>(v);
if(dot)
{
std::cerr << "(EE) Read a deprecated GxsTrans outgoing item. Converting to new format..." << std::endl;
OutgoingRecord ot(dot->recipient,dot->clientService,&dot->mailData[0],dot->mailData.size()) ;
ot.status = dot->status ;
ot.author.clear(); // These 3 fields cannot be stored in mailItem.meta, which is not serialised, so they are lost.
ot.group_id.clear() ;
ot.sent_ts = 0;
ot.mailItem = dot->mailItem ;
ot.presignedReceipt = dot->presignedReceipt;
RS_STACK_MUTEX(mOutgoingMutex);
mOutgoingQueue.insert(prMap::value_type(ot.mailItem.mailId, ot));
#ifdef DEBUG_GXSTRANS
std::cerr << "Loaded outgoing item (converted), ID " << std::hex << std::setfill('0') << std::setw(16) << ot.mailItem.mailId<< std::dec << ", Group id: " << ot.group_id << ", TS=" << ot.sent_ts << std::endl;
#endif
}
delete v;
break;
}
case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM:
{
OutgoingRecord* ot = dynamic_cast<OutgoingRecord*>(v);
@ -903,6 +1182,10 @@ bool p3GxsTrans::loadList(std::list<RsItem *>&loadList)
RS_STACK_MUTEX(mOutgoingMutex);
mOutgoingQueue.insert(
prMap::value_type(ot->mailItem.mailId, *ot));
#ifdef DEBUG_GXSTRANS
std::cerr << "Loading outgoing item, ID " << std::hex << std::setfill('0') << std::setw(16) << ot->mailItem.mailId<< std::dec << "Group id: " << ot->group_id << ", TS=" << ot->sent_ts << std::endl;
#endif
}
delete v;
break;
@ -917,9 +1200,106 @@ bool p3GxsTrans::loadList(std::list<RsItem *>&loadList)
break;
}
#ifdef DEBUG_GXSTRANS
std::cout << "p3GxsTrans::loadList(...) " << loadList.size() << " "
<< mIngoingQueue.size() << " " << mOutgoingQueue.size()
<< mIncomingQueue.size() << " " << mOutgoingQueue.size()
<< std::endl;
#endif
return true;
}
bool p3GxsTrans::acceptNewMessage(const RsGxsMsgMetaData *msgMeta,uint32_t msg_size)
{
// 1 - check the total size of the msgs for the author of this particular msg.
// 2 - Reject depending on embedded limits.
// Depending on reputation, the messages will be rejected:
//
// Reputation | Maximum msg count | Maximum msg size
// ------------+----------------------+------------------
// Negative | 0 | 0 // This is already handled by the anti-spam
// R-Negative | 10 | 10k
// Neutral | 100 | 20k
// R-Positive | 400 | 1M
// Positive | 1000 | 2M
// Ideally these values should be left as user-defined parameters, with the
// default values below used as backup.
static const uint32_t GXSTRANS_MAX_COUNT_REMOTELY_NEGATIVE_DEFAULT = 10 ;
static const uint32_t GXSTRANS_MAX_COUNT_NEUTRAL_DEFAULT = 40 ;
static const uint32_t GXSTRANS_MAX_COUNT_REMOTELY_POSITIVE_DEFAULT = 400 ;
static const uint32_t GXSTRANS_MAX_COUNT_LOCALLY_POSITIVE_DEFAULT = 1000 ;
static const uint32_t GXSTRANS_MAX_SIZE_REMOTELY_NEGATIVE_DEFAULT = 10 * 1024 ;
static const uint32_t GXSTRANS_MAX_SIZE_NEUTRAL_DEFAULT = 200 * 1024 ;
static const uint32_t GXSTRANS_MAX_SIZE_REMOTELY_POSITIVE_DEFAULT = 1024 * 1024 ;
static const uint32_t GXSTRANS_MAX_SIZE_LOCALLY_POSITIVE_DEFAULT = 2 * 1024 * 1024 ;
uint32_t max_count = 0 ;
uint32_t max_size = 0 ;
uint32_t identity_flags = 0 ;
RsReputations::ReputationLevel rep_lev = rsReputations->overallReputationLevel(msgMeta->mAuthorId,&identity_flags);
switch(rep_lev)
{
case RsReputations::REPUTATION_REMOTELY_NEGATIVE: max_count = GXSTRANS_MAX_COUNT_REMOTELY_NEGATIVE_DEFAULT;
max_size = GXSTRANS_MAX_SIZE_REMOTELY_NEGATIVE_DEFAULT;
break ;
case RsReputations::REPUTATION_NEUTRAL: max_count = GXSTRANS_MAX_COUNT_NEUTRAL_DEFAULT;
max_size = GXSTRANS_MAX_SIZE_NEUTRAL_DEFAULT;
break ;
case RsReputations::REPUTATION_REMOTELY_POSITIVE: max_count = GXSTRANS_MAX_COUNT_REMOTELY_POSITIVE_DEFAULT;
max_size = GXSTRANS_MAX_SIZE_REMOTELY_POSITIVE_DEFAULT;
break ;
case RsReputations::REPUTATION_LOCALLY_POSITIVE: max_count = GXSTRANS_MAX_COUNT_LOCALLY_POSITIVE_DEFAULT;
max_size = GXSTRANS_MAX_SIZE_LOCALLY_POSITIVE_DEFAULT;
break ;
default:
case RsReputations::REPUTATION_LOCALLY_NEGATIVE: max_count = 0 ;
max_size = 0 ;
break ;
}
bool pgp_linked = identity_flags & RS_IDENTITY_FLAGS_PGP_LINKED ;
if(rep_lev <= RsReputations::REPUTATION_NEUTRAL && !pgp_linked)
{
max_count /= 10 ;
max_size /= 10 ;
}
RS_STACK_MUTEX(mPerUserStatsMutex);
MsgSizeCount& s(per_user_statistics[msgMeta->mAuthorId]) ;
#ifdef DEBUG_GXSTRANS
std::cerr << "GxsTrans::acceptMessage(): size=" << msg_size << ", grp=" << msgMeta->mGroupId << ", gxs_id=" << msgMeta->mAuthorId << ", pgp_linked=" << pgp_linked << ", current (size,cnt)=("
<< s.size << "," << s.count << ") reputation=" << rep_lev << ", limits=(" << max_size << "," << max_count << ") " ;
#endif
if(s.size + msg_size > max_size || 1+s.count > max_count)
{
#ifdef DEBUG_GXSTRANS
std::cerr << "=> rejected." << std::endl;
#endif
return false ;
}
else
{
#ifdef DEBUG_GXSTRANS
std::cerr << "=> accepted." << std::endl;
#endif
s.count++ ;
s.size += msg_size ; // update the statistics, so that it's not possible to pass a bunch of msgs at once below the limits.
return true ;
}
}

View File

@ -57,6 +57,14 @@ struct GxsTransClient
GxsTransSendStatus status ) = 0;
};
struct MsgSizeCount
{
MsgSizeCount() : size(0),count(0) {}
uint32_t size ;
uint32_t count ;
};
/**
* @brief p3GxsTrans is a mail delivery service based on GXS.
* p3GxsTrans is capable of asynchronous mail delivery and acknowledgement.
@ -84,15 +92,17 @@ public:
p3IdService& identities ) :
RsGenExchange( gds, nes, new RsGxsTransSerializer(),
RS_SERVICE_TYPE_GXS_TRANS, &identities,
AuthenPolicy(), GXS_STORAGE_PERIOD ),
AuthenPolicy()),
GxsTokenQueue(this),
RsGxsTrans(this),
mIdService(identities),
mServClientsMutex("p3GxsTrans client services map mutex"),
mOutgoingMutex("p3GxsTrans outgoing queue map mutex"),
mIngoingMutex("p3GxsTrans ingoing queue map mutex")
mIngoingMutex("p3GxsTrans ingoing queue map mutex"),
mPerUserStatsMutex("p3GxsTrans user stats mutex"),
mDataMutex("p3GxsTrans data mutex")
{
mLastMsgCleanup = time(NULL) - 60; // to be changed into 0
mLastMsgCleanup = time(NULL) - MAX_DELAY_BETWEEN_CLEANUPS + 30; // always check 30 secs after start
mCleanupThread = NULL ;
}
@ -140,10 +150,12 @@ public:
/// @see RsGenExchange::getServiceInfo()
virtual RsServiceInfo getServiceInfo() { return RsServiceInfo( RS_SERVICE_TYPE_GXS_TRANS, "GXS Mails", 0, 1, 0, 1 ); }
static const uint32_t GXS_STORAGE_PERIOD = 15*86400; // 15 days.
static const uint32_t GXS_SYNC_PERIOD = 15*86400;
private:
/** Time interval of inactivity before a distribution group is unsubscribed.
* Approximatively 3 months seems ok ATM. */
const static int32_t UNUSED_GROUP_UNSUBSCRIBE_INTERVAL = 0x76A700;
const static int32_t UNUSED_GROUP_UNSUBSCRIBE_INTERVAL = 16*86400; // 16 days
/**
* This should be as little as possible as the size of the database can grow
@ -158,8 +170,7 @@ private:
* signed acknowledged is received for each of them.
* Two weeks seems fair ATM.
*/
static const uint32_t GXS_STORAGE_PERIOD = 0x127500;
static const uint32_t MAX_DELAY_BETWEEN_CLEANUPS = 1203; // every 20 mins. Could be less.
static const uint32_t MAX_DELAY_BETWEEN_CLEANUPS ; // every 20 mins. Could be less.
time_t mLastMsgCleanup ;
@ -193,7 +204,7 @@ private:
typedef std::map<RsGxsTransId, OutgoingRecord> prMap;
prMap mOutgoingQueue;
RsMutex mOutgoingMutex;
void processOutgoingRecord(OutgoingRecord& r);
void locked_processOutgoingRecord(OutgoingRecord& r);
/**
* @brief Ingoing mail and receipt processing queue.
@ -204,8 +215,8 @@ private:
* item to not being processed and memleaked multimap is used instead of map
* for incoming queue.
*/
typedef std::unordered_multimap<RsGxsTransId, RsGxsTransBaseItem*> inMap;
inMap mIngoingQueue;
typedef std::unordered_multimap<RsGxsTransId, RsGxsTransBaseMsgItem*> inMap;
inMap mIncomingQueue;
RsMutex mIngoingMutex;
/// @see GxsTokenQueue::handleResponse(uint32_t token, uint32_t req_type)
@ -244,7 +255,7 @@ private:
* @return true if preferredGroupId has been supeseded by potentialGrId
* false otherwise.
*/
bool inline supersedePreferredGroup(const RsGxsGroupId& potentialGrId)
bool inline locked_supersedePreferredGroup(const RsGxsGroupId& potentialGrId)
{
if(mPreferredGroupId < potentialGrId)
{
@ -282,18 +293,38 @@ private:
enum CheckState { CheckStart, CheckChecking };
public:
GxsTransIntegrityCleanupThread(RsGeneralDataService *const dataService): mDs(dataService) {}
GxsTransIntegrityCleanupThread(RsGeneralDataService *const dataService): mDs(dataService),mMtx("GxsTransIntegrityCheck") { mDone=false;}
bool isDone();
void run();
void getDeletedIds(std::list<RsGxsGroupId>& grpIds, std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >& msgIds);
private:
void getMessagesToDelete(GxsMsgReq& req) ;
void getPerUserStatistics(std::map<RsGxsId,MsgSizeCount>& m) ;
private:
RsGeneralDataService* const mDs;
RsMutex mMtx ;
GxsMsgReq mMsgToDel ;
std::map<RsGxsId,MsgSizeCount> total_message_size_and_count;
bool mDone ;
};
// Overloaded from RsGenExchange.
bool acceptNewMessage(const RsGxsMsgMetaData *msgMeta, uint32_t size) ;
GxsTransIntegrityCleanupThread *mCleanupThread ;
// statistics of the load across all groups, per user.
RsMutex mPerUserStatsMutex;
std::map<RsGxsId,MsgSizeCount> per_user_statistics ;
// Mutex to protect local data
RsMutex mDataMutex;
};

View File

@ -21,10 +21,11 @@
const RsGxsId RsGxsTransMailItem::allRecipientsHint("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
OutgoingRecord::OutgoingRecord() :
RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_TRANS,
static_cast<uint8_t>(GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM) )
{ clear();}
OutgoingRecord_deprecated::OutgoingRecord_deprecated()
: RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_TRANS, static_cast<uint8_t>(GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM_deprecated) ) { clear();}
OutgoingRecord::OutgoingRecord()
: RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_TRANS, static_cast<uint8_t>(GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM) ) { clear();}
OutgoingRecord::OutgoingRecord( RsGxsId rec, GxsTransSubServices cs,
const uint8_t* data, uint32_t size ) :
@ -41,8 +42,7 @@ OutgoingRecord::OutgoingRecord( RsGxsId rec, GxsTransSubServices cs,
RS_REGISTER_ITEM_TYPE(RsGxsTransMailItem) // for mailItem
RS_REGISTER_ITEM_TYPE(RsNxsTransPresignedReceipt) // for presignedReceipt
void OutgoingRecord::serial_process(RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx)
void OutgoingRecord_deprecated::serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx)
{
RS_REGISTER_SERIAL_MEMBER_TYPED(status, uint8_t);
RS_REGISTER_SERIAL_MEMBER(recipient);
@ -51,3 +51,17 @@ void OutgoingRecord::serial_process(RsGenericSerializer::SerializeJob j,
RS_REGISTER_SERIAL_MEMBER_TYPED(clientService, uint16_t);
RS_REGISTER_SERIAL_MEMBER(presignedReceipt);
}
void OutgoingRecord::serial_process(RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx)
{
RS_REGISTER_SERIAL_MEMBER_TYPED(status, uint8_t);
RS_REGISTER_SERIAL_MEMBER(recipient);
RS_REGISTER_SERIAL_MEMBER(author);
RS_REGISTER_SERIAL_MEMBER(group_id);
RS_REGISTER_SERIAL_MEMBER(sent_ts);
RS_REGISTER_SERIAL_MEMBER(mailItem);
RS_REGISTER_SERIAL_MEMBER(mailData);
RS_REGISTER_SERIAL_MEMBER_TYPED(clientService, uint16_t);
RS_REGISTER_SERIAL_MEMBER(presignedReceipt);
}

View File

@ -36,14 +36,14 @@ public:
virtual ~RsNxsTransPresignedReceipt() {}
};
class RsGxsTransBaseItem : public RsGxsMsgItem
class RsGxsTransBaseMsgItem : public RsGxsMsgItem
{
public:
RsGxsTransBaseItem(GxsTransItemsSubtypes subtype) :
RsGxsTransBaseMsgItem(GxsTransItemsSubtypes subtype) :
RsGxsMsgItem( RS_SERVICE_TYPE_GXS_TRANS,
static_cast<uint8_t>(subtype) ), mailId(0) {}
virtual ~RsGxsTransBaseItem() {}
virtual ~RsGxsTransBaseMsgItem() {}
RsGxsTransId mailId;
@ -58,10 +58,10 @@ public:
{ RS_REGISTER_SERIAL_MEMBER_TYPED(mailId, uint64_t); }
};
class RsGxsTransPresignedReceipt : public RsGxsTransBaseItem
class RsGxsTransPresignedReceipt : public RsGxsTransBaseMsgItem
{
public:
RsGxsTransPresignedReceipt() : RsGxsTransBaseItem(GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT) {}
RsGxsTransPresignedReceipt() : RsGxsTransBaseMsgItem(GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT) {}
virtual ~RsGxsTransPresignedReceipt() {}
};
@ -72,11 +72,11 @@ enum class RsGxsTransEncryptionMode : uint8_t
UNDEFINED_ENCRYPTION = 250
};
class RsGxsTransMailItem : public RsGxsTransBaseItem
class RsGxsTransMailItem : public RsGxsTransBaseMsgItem
{
public:
RsGxsTransMailItem() :
RsGxsTransBaseItem(GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL),
RsGxsTransBaseMsgItem(GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL),
cryptoType(RsGxsTransEncryptionMode::UNDEFINED_ENCRYPTION) {}
virtual ~RsGxsTransMailItem() {}
@ -139,7 +139,7 @@ public:
void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx )
{
RsGxsTransBaseItem::serial_process(j, ctx);
RsGxsTransBaseMsgItem::serial_process(j, ctx);
RS_REGISTER_SERIAL_MEMBER_TYPED(cryptoType, uint8_t);
RS_REGISTER_SERIAL_MEMBER(recipientHint);
RS_REGISTER_SERIAL_MEMBER(payload);
@ -147,7 +147,7 @@ public:
void clear()
{
RsGxsTransBaseItem::clear();
RsGxsTransBaseMsgItem::clear();
cryptoType = RsGxsTransEncryptionMode::UNDEFINED_ENCRYPTION;
recipientHint.clear();
payload.clear();
@ -183,6 +183,33 @@ public:
class RsGxsTransSerializer;
class OutgoingRecord_deprecated : public RsItem
{
public:
OutgoingRecord_deprecated( RsGxsId rec, GxsTransSubServices cs, const uint8_t* data, uint32_t size );
virtual ~OutgoingRecord_deprecated() {}
GxsTransSendStatus status;
RsGxsId recipient;
/// Don't use a pointer would be invalid after publish
RsGxsTransMailItem mailItem;
std::vector<uint8_t> mailData;
GxsTransSubServices clientService;
RsNxsTransPresignedReceipt presignedReceipt;
void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx );
void clear() {}
private:
friend class RsGxsTransSerializer;
OutgoingRecord_deprecated();
};
class OutgoingRecord : public RsItem
{
public:
@ -191,12 +218,19 @@ public:
virtual ~OutgoingRecord() {}
GxsTransSendStatus status;
RsGxsId recipient;
GxsTransSendStatus status;
RsGxsId recipient;
RsGxsId author; // These 3 fields cannot be stored in mailItem.meta, which is not serialised.
RsGxsGroupId group_id ;
uint32_t sent_ts ;
/// Don't use a pointer would be invalid after publish
RsGxsTransMailItem mailItem;
std::vector<uint8_t> mailData;
GxsTransSubServices clientService;
RsNxsTransPresignedReceipt presignedReceipt;
void serial_process( RsGenericSerializer::SerializeJob j,
@ -225,6 +259,7 @@ public:
case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL: return new RsGxsTransMailItem();
case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT: return new RsGxsTransPresignedReceipt();
case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_GROUP: return new RsGxsTransGroupItem();
case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM_deprecated: return new OutgoingRecord_deprecated();
case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM: return new OutgoingRecord();
default: return NULL;
}

View File

@ -211,7 +211,7 @@ void p3GxsTunnelService::flush()
if(it->second.last_contact+20+GXS_TUNNEL_KEEP_ALIVE_TIMEOUT < now && it->second.status == RS_GXS_TUNNEL_STATUS_CAN_TALK)
{
#ifdef DEBUG_GXS_TUNNEL
std::cerr << "(II) GxsTunnelService:: connexion interrupted with peer." << std::endl;
std::cerr << "(II) GxsTunnelService:: connection interrupted with peer." << std::endl;
#endif
it->second.status = RS_GXS_TUNNEL_STATUS_TUNNEL_DN ;

View File

@ -599,7 +599,8 @@ bool AuthSSLimpl::SignData(const void *data, const uint32_t len, std::string &si
EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
unsigned int signlen = EVP_PKEY_size(mOwnPrivateKey);
unsigned char signature[signlen] = { 0 };
unsigned char signature[signlen] ;
memset(signature,0,signlen) ;
if (0 == EVP_SignInit(mdctx, EVP_sha1()))
{

View File

@ -1528,7 +1528,7 @@ bool p3PeerMgrIMPL::addCandidateForOwnExternalAddress(const RsPeerId &from, cons
if((!rsBanList->isAddressAccepted(addr_filtered,RSBANLIST_CHECKING_FLAGS_WHITELIST)) && (!sockaddr_storage_sameip(own_addr,addr_filtered)))
{
std::cerr << " Peer " << from << " reports a connexion address (" << sockaddr_storage_iptostring(addr_filtered) <<") that is not your current external address (" << sockaddr_storage_iptostring(own_addr) << "). This is weird." << std::endl;
std::cerr << " Peer " << from << " reports a connection address (" << sockaddr_storage_iptostring(addr_filtered) <<") that is not your current external address (" << sockaddr_storage_iptostring(own_addr) << "). This is weird." << std::endl;
RsServer::notify()->AddFeedItem(RS_FEED_ITEM_SEC_IP_WRONG_EXTERNAL_IP_REPORTED, from.toStdString(), sockaddr_storage_iptostring(own_addr), sockaddr_storage_iptostring(addr));
}

View File

@ -46,6 +46,10 @@ const uint32_t RS_FILE_CTRL_FORCE_CHECK = 0x00000400;
const uint32_t RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT = 0x00000001 ;
const uint32_t RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE = 0x00000002 ;
const uint32_t RS_FILE_PERM_DIRECT_DL_YES = 0x00000001 ;
const uint32_t RS_FILE_PERM_DIRECT_DL_NO = 0x00000002 ;
const uint32_t RS_FILE_PERM_DIRECT_DL_PER_USER = 0x00000003 ;
const uint32_t RS_FILE_RATE_TRICKLE = 0x00000001;
const uint32_t RS_FILE_RATE_SLOW = 0x00000002;
const uint32_t RS_FILE_RATE_STANDARD = 0x00000003;
@ -165,10 +169,12 @@ class RsFiles
virtual void setFreeDiskSpaceLimit(uint32_t size_in_mb) =0;
virtual bool FileControl(const RsFileHash& hash, uint32_t flags) = 0;
virtual bool FileClearCompleted() = 0;
virtual void setDefaultEncryptionPolicy(uint32_t policy)=0 ; // RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT/PERMISSIVE
virtual uint32_t defaultEncryptionPolicy()=0 ;
virtual void setMaxUploadSlotsPerFriend(uint32_t n)=0 ;
virtual uint32_t getMaxUploadSlotsPerFriend()=0 ;
virtual void setDefaultEncryptionPolicy(uint32_t policy)=0; // RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT/PERMISSIVE
virtual uint32_t defaultEncryptionPolicy()=0;
virtual void setMaxUploadSlotsPerFriend(uint32_t n)=0;
virtual uint32_t getMaxUploadSlotsPerFriend()=0;
virtual void setFilePermDirectDL(uint32_t perm)=0;
virtual uint32_t filePermDirectDL()=0;
/***
* Control of Downloads Priority.

View File

@ -142,6 +142,7 @@ public:
/* standard load */
virtual bool getGroupData(const uint32_t &token, std::vector<RsGxsCircleGroup> &groups) = 0;
virtual bool getMsgData(const uint32_t &token, std::vector<RsGxsCircleMsg> &msgs) = 0;
/* make new group */
virtual void createGroup(uint32_t& token, RsGxsCircleGroup &group) = 0;

View File

@ -16,10 +16,11 @@ enum class GxsTransSubServices : uint16_t
/// Values must fit into uint8_t
enum class GxsTransItemsSubtypes : uint8_t
{
GXS_TRANS_SUBTYPE_MAIL = 0x01,
GXS_TRANS_SUBTYPE_RECEIPT = 0x02,
GXS_TRANS_SUBTYPE_GROUP = 0x03,
OUTGOING_RECORD_ITEM = 0x04
GXS_TRANS_SUBTYPE_MAIL = 0x01,
GXS_TRANS_SUBTYPE_RECEIPT = 0x02,
GXS_TRANS_SUBTYPE_GROUP = 0x03,
OUTGOING_RECORD_ITEM_deprecated = 0x04,
OUTGOING_RECORD_ITEM = 0x05
};
enum class GxsTransSendStatus : uint8_t

View File

@ -490,7 +490,10 @@ virtual ChatLobbyId createChatLobby(const std::string& lobby_name,const RsGxsId&
virtual uint32_t getDistantChatPermissionFlags()=0 ;
virtual bool setDistantChatPermissionFlags(uint32_t flags)=0 ;
virtual bool initiateDistantChatConnexion(const RsGxsId& to_pid,const RsGxsId& from_pid,DistantChatPeerId& pid,uint32_t& error_code) = 0;
virtual bool initiateDistantChatConnexion(
const RsGxsId& to_pid, const RsGxsId& from_pid,
DistantChatPeerId& pid, uint32_t& error_code,
bool notify = true ) = 0;
virtual bool getDistantChatStatus(const DistantChatPeerId& pid,DistantChatPeerInfo& info)=0;
virtual bool closeDistantChatConnexion(const DistantChatPeerId& pid)=0;

View File

@ -77,6 +77,7 @@ const uint32_t RS_FEED_TYPE_FILES = 0x0400;
const uint32_t RS_FEED_TYPE_SECURITY = 0x0800;
const uint32_t RS_FEED_TYPE_POSTED = 0x1000;
const uint32_t RS_FEED_TYPE_SECURITY_IP = 0x2000;
const uint32_t RS_FEED_TYPE_CIRCLE = 0x4000;
const uint32_t RS_FEED_ITEM_PEER_CONNECT = RS_FEED_TYPE_PEER | 0x0001;
const uint32_t RS_FEED_ITEM_PEER_DISCONNECT = RS_FEED_TYPE_PEER | 0x0002;
@ -114,9 +115,12 @@ const uint32_t RS_FEED_ITEM_POSTED_NEW = RS_FEED_TYPE_POSTED | 0x0001;
//const uint32_t RS_FEED_ITEM_POSTED_UPDATE = RS_FEED_TYPE_POSTED | 0x0002;
const uint32_t RS_FEED_ITEM_POSTED_MSG = RS_FEED_TYPE_POSTED | 0x0003;
const uint32_t RS_FEED_ITEM_CHAT_NEW = RS_FEED_TYPE_CHAT | 0x0001;
const uint32_t RS_FEED_ITEM_MESSAGE = RS_FEED_TYPE_MSG | 0x0001;
const uint32_t RS_FEED_ITEM_FILES_NEW = RS_FEED_TYPE_FILES | 0x0001;
const uint32_t RS_FEED_ITEM_CHAT_NEW = RS_FEED_TYPE_CHAT | 0x0001;
const uint32_t RS_FEED_ITEM_MESSAGE = RS_FEED_TYPE_MSG | 0x0001;
const uint32_t RS_FEED_ITEM_FILES_NEW = RS_FEED_TYPE_FILES | 0x0001;
const uint32_t RS_FEED_ITEM_CIRCLE_MEMB_REQ = RS_FEED_TYPE_CIRCLE | 0x0001;
const uint32_t RS_FEED_ITEM_CIRCLE_INVIT_REC = RS_FEED_TYPE_CIRCLE | 0x0002;
const uint32_t RS_MESSAGE_CONNECT_ATTEMPT = 0x0001;

View File

@ -55,7 +55,8 @@ void RsGxsCircleSubscriptionRequestItem::clear()
void RsGxsCircleMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
{
RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,msg.stuff,"msg.stuff") ;
//RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,mMsg.stuff,"mMsg.stuff") ;//Should be this but not retrocompatible...
RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,mMsg.stuff,"msg.stuff") ;
}
void RsGxsCircleSubscriptionRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
@ -74,7 +75,7 @@ void RsGxsCircleGroupItem::serial_process(RsGenericSerializer::SerializeJob j,Rs
void RsGxsCircleMsgItem::clear()
{
msg.stuff.clear();
mMsg.stuff.clear();
}
void RsGxsCircleGroupItem::clear()

View File

@ -78,7 +78,7 @@ public:
virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx);
RsGxsCircleMsg msg;
RsGxsCircleMsg mMsg;
};
class RsGxsCircleSubscriptionRequestItem: public RsGxsMsgItem

View File

@ -68,7 +68,8 @@ public:
msg_req_delay = RS_GXS_DEFAULT_MSG_REQ_PERIOD ;
max_visible_count = 0 ;
update_TS = 0 ;
statistics_update_TS = 0 ;
last_group_modification_TS = 0 ;
}
uint32_t msg_keep_delay ; // delay after which we discard the posts
@ -77,7 +78,8 @@ public:
RsTlvPeerIdSet suppliers; // list of friends who feed this group
uint32_t max_visible_count ; // max visible count reported by contributing friends
time_t update_TS ; // last time the max visible count was updated.
time_t statistics_update_TS ; // last time the max visible count was updated.
time_t last_group_modification_TS ; // last time the group was modified, either in meta data or in the list of messages posted in it.
};
class RsGxsGrpConfigItem : public RsGxsNetServiceItem, public RsGxsGrpConfig

View File

@ -520,9 +520,12 @@ void p3Msgs::getPendingChatLobbyInvites(std::list<ChatLobbyInvite>& invites)
{
mChatSrv->getPendingChatLobbyInvites(invites) ;
}
bool p3Msgs::initiateDistantChatConnexion(const RsGxsId& to_gxs_id,const RsGxsId& from_gxs_id,DistantChatPeerId& pid,uint32_t& error_code)
bool p3Msgs::initiateDistantChatConnexion(
const RsGxsId& to_gxs_id, const RsGxsId& from_gxs_id,
DistantChatPeerId& pid, uint32_t& error_code, bool notify )
{
return mChatSrv->initiateDistantChatConnexion(to_gxs_id,from_gxs_id,pid,error_code) ;
return mChatSrv->initiateDistantChatConnexion( to_gxs_id, from_gxs_id,
pid, error_code, notify );
}
bool p3Msgs::getDistantChatStatus(const DistantChatPeerId& pid,DistantChatPeerInfo& info)
{

View File

@ -159,7 +159,11 @@ class p3Msgs: public RsMsgs
virtual bool getLobbyAutoSubscribe(const ChatLobbyId& lobby_id);
virtual ChatLobbyId createChatLobby(const std::string& lobby_name,const RsGxsId& lobby_identity,const std::string& lobby_topic,const std::set<RsPeerId>& invited_friends,ChatLobbyFlags privacy_type) ;
virtual bool initiateDistantChatConnexion(const RsGxsId& to_gxs_id, const RsGxsId& from_gxs_id, DistantChatPeerId &pid, uint32_t& error_code) ;
virtual bool initiateDistantChatConnexion(
const RsGxsId& to_gxs_id, const RsGxsId& from_gxs_id,
DistantChatPeerId &pid, uint32_t& error_code,
bool notify = true );
virtual bool getDistantChatStatus(const DistantChatPeerId& gxs_id,DistantChatPeerInfo& info);
virtual bool closeDistantChatConnexion(const DistantChatPeerId &pid) ;

View File

@ -1298,16 +1298,10 @@ int RsServer::StartupRetroShare()
//
mPluginsManager->setServiceControl(serviceCtrl) ;
// std::cerr << "rsinitconf (core 1) = " << (void*)rsInitConfig<<std::endl;
// std::cerr << "gxs_passwd (core 1) = " << (void*)&rsInitConfig->gxs_passwd<<" \"" << rsInitConfig->gxs_passwd << "\""<< std::endl;
// Now load the plugins. This parses the available SO/DLL files for known symbols.
//
mPluginsManager->loadPlugins(plugins_directories) ;
// std::cerr << "rsinitconf (core 1) = " << (void*)rsInitConfig<<std::endl;
// std::cerr << "gxs_passwd (core 2) = " << (void*)&rsInitConfig->gxs_passwd<< " \"" << rsInitConfig->gxs_passwd << "\""<< std::endl;
// Also load some plugins explicitly. This is helpful for
// - developping plugins
//
@ -1375,7 +1369,7 @@ int RsServer::StartupRetroShare()
true, // synchronise group automatic
true); // sync messages automatic, since they contain subscription requests.
mGxsCircles->setNetworkExchangeService(gxscircles_ns) ;
mGxsCircles->setNetworkExchangeService(gxscircles_ns) ;
/**** Posted GXS service ****/
@ -1392,8 +1386,7 @@ int RsServer::StartupRetroShare()
mReputations, mGxsCircles,mGxsIdService,
pgpAuxUtils);
mPosted->setNetworkExchangeService(posted_ns) ;
mPosted->setNetworkExchangeService(posted_ns) ;
/**** Wiki GXS service ****/
@ -1493,10 +1486,12 @@ int RsServer::StartupRetroShare()
currGxsDir + "/", "gxstrans_db", RS_SERVICE_TYPE_GXS_TRANS,
NULL, rsInitConfig->gxs_passwd );
mGxsTrans = new p3GxsTrans(gxstrans_ds, NULL, *mGxsIdService);
RsGxsNetService* gxstrans_ns = new RsGxsNetService(
RS_SERVICE_TYPE_GXS_TRANS, gxstrans_ds, nxsMgr, mGxsTrans,
mGxsTrans->getServiceInfo(), mReputations, mGxsCircles,
mGxsIdService, pgpAuxUtils);
mGxsIdService, pgpAuxUtils,true,true,p3GxsTrans::GXS_STORAGE_PERIOD,p3GxsTrans::GXS_SYNC_PERIOD);
mGxsTrans->setNetworkExchangeService(gxstrans_ns);
pqih->addService(gxstrans_ns, true);
# endif // RS_GXS_TRANS

View File

@ -34,7 +34,7 @@ static const int sleepFactorDefault = 10; // 0.5s
static const int sleepFactorFast = 1; // 0.05s
static const int sleepFactorSlow = 20; // 1s
static struct RsLog::logInfo i2pBobLogInfo = {RsLog::Debug_All, "p3I2pBob"};
static struct RsLog::logInfo i2pBobLogInfo = {RsLog::Default, "p3I2pBob"};
static const time_t selfCheckPeroid = 30;

View File

@ -35,6 +35,7 @@
#include "pgp/pgpauxutils.h"
#include "retroshare/rsgxscircles.h"
#include "retroshare/rspeers.h"
#include "rsserver/p3face.h"
#include <sstream>
#include <stdio.h>
@ -194,30 +195,38 @@ void p3GxsCircles::service_tick()
void p3GxsCircles::notifyChanges(std::vector<RsGxsNotify *> &changes)
{
#ifdef DEBUG_CIRCLES
std::cerr << "p3GxsCircles::notifyChanges()";
std::cerr << std::endl;
std::cerr << "p3GxsCircles::notifyChanges()";
std::cerr << std::endl;
#endif
std::vector<RsGxsNotify *>::iterator it;
for(it = changes.begin(); it != changes.end(); ++it)
{
RsGxsGroupChange *groupChange = dynamic_cast<RsGxsGroupChange *>(*it);
RsGxsMsgChange *msgChange = dynamic_cast<RsGxsMsgChange *>(*it);
p3Notify *notify = RsServer::notify();
std::vector<RsGxsNotify *>::iterator it;
for(it = changes.begin(); it != changes.end(); ++it)
{
RsGxsGroupChange *groupChange = dynamic_cast<RsGxsGroupChange *>(*it);
RsGxsMsgChange *msgChange = dynamic_cast<RsGxsMsgChange *>(*it);
RsGxsNotify *c = *it;
if (msgChange && !msgChange->metaChange())
{
if (msgChange && !msgChange->metaChange())
{
#ifdef DEBUG_CIRCLES
std::cerr << " Found circle Message Change Notification" << std::endl;
std::cerr << " Found circle Message Change Notification" << std::endl;
#endif
for(std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >::iterator mit = msgChange->msgChangeMap.begin(); mit != msgChange->msgChangeMap.end(); ++mit)
{
for(std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >::iterator mit = msgChange->msgChangeMap.begin(); mit != msgChange->msgChangeMap.end(); ++mit)
{
#ifdef DEBUG_CIRCLES
std::cerr << " Msgs for Group: " << mit->first << std::endl;
std::cerr << " Msgs for Group: " << mit->first << std::endl;
#endif
for(std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >::const_iterator it2(msgChange->msgChangeMap.begin());it2!=msgChange->msgChangeMap.end();++it2)
force_cache_reload(RsGxsCircleId(it2->first)) ;
}
}
force_cache_reload(RsGxsCircleId(mit->first));
if (notify && (c->getType() == RsGxsNotify::TYPE_RECEIVE) )
for (std::vector<RsGxsMessageId>::const_iterator msgIdIt(mit->second.begin()), end(mit->second.end()); msgIdIt != end; ++msgIdIt)
{
const RsGxsMessageId& msgId = *msgIdIt;
notify->AddFeedItem(RS_FEED_ITEM_CIRCLE_MEMB_REQ,RsGxsCircleId(mit->first).toStdString(),msgId.toStdString());
}
}
}
/* add groups to ExternalIdList (Might get Personal Circles here until NetChecks in place) */
if (groupChange && !groupChange->metaChange())
@ -245,16 +254,19 @@ void p3GxsCircles::notifyChanges(std::vector<RsGxsNotify *> &changes)
}
}
if(groupChange)
for(std::list<RsGxsGroupId>::const_iterator git(groupChange->mGrpIdList.begin());git!=groupChange->mGrpIdList.end();++git)
{
if(groupChange)
for(std::list<RsGxsGroupId>::const_iterator git(groupChange->mGrpIdList.begin());git!=groupChange->mGrpIdList.end();++git)
{
#ifdef DEBUG_CIRCLES
std::cerr << " forcing cache loading for circle " << *git << " in order to trigger subscribe update." << std::endl;
std::cerr << " forcing cache loading for circle " << *git << " in order to trigger subscribe update." << std::endl;
#endif
force_cache_reload(RsGxsCircleId(*git)) ;
}
}
RsGxsIfaceHelper::receiveChanges(changes); // this clear up the vector and delete its elements
force_cache_reload(RsGxsCircleId(*git)) ;
if (notify && (c->getType() == RsGxsNotify::TYPE_RECEIVE) )
notify->AddFeedItem(RS_FEED_ITEM_CIRCLE_INVIT_REC,RsGxsCircleId(*git).toStdString(),"");
}
}
RsGxsIfaceHelper::receiveChanges(changes); // this clear up the vector and delete its elements
}
/********************************************************************************/
@ -496,6 +508,62 @@ bool p3GxsCircles::getGroupData(const uint32_t &token, std::vector<RsGxsCircleGr
/********************************************************************************/
/********************************************************************************/
bool p3GxsCircles::getMsgData(const uint32_t &token, std::vector<RsGxsCircleMsg> &msgs)
{
GxsMsgDataMap msgData;
bool ok = RsGenExchange::getMsgData(token, msgData);
if(ok)
{
GxsMsgDataMap::iterator mit = msgData.begin();
for(; mit != msgData.end(); ++mit)
{
std::vector<RsGxsMsgItem*>& msgItems = mit->second;
std::vector<RsGxsMsgItem*>::iterator vit = msgItems.begin();
for(; vit != msgItems.end(); ++vit)
{
RsGxsCircleMsgItem* item = dynamic_cast<RsGxsCircleMsgItem*>(*vit);
RsGxsCircleSubscriptionRequestItem* rsItem = dynamic_cast<RsGxsCircleSubscriptionRequestItem*>(*vit);
if(item)
{
RsGxsCircleMsg msg = item->mMsg;
msg.mMeta = item->meta;
msgs.push_back(msg);
delete item;
}
else if (rsItem)
{
RsGxsCircleMsg msg ;//= rsItem->mMsg;
msg.mMeta = rsItem->meta;
switch (rsItem->subscription_type)
{
case RsGxsCircleSubscriptionRequestItem::SUBSCRIPTION_REQUEST_UNKNOWN:
msg.stuff.clear();
break;
case RsGxsCircleSubscriptionRequestItem::SUBSCRIPTION_REQUEST_SUBSCRIBE:
msg.stuff="SUBSCRIPTION_REQUEST_SUBSCRIBE";
break;
case RsGxsCircleSubscriptionRequestItem::SUBSCRIPTION_REQUEST_UNSUBSCRIBE:
msg.stuff="SUBSCRIPTION_REQUEST_UNSUBSCRIBE";
break;
}
msgs.push_back(msg);
delete rsItem;
}
else
{
std::cerr << "Not a GxsCircleMsgItem, deleting!" << std::endl;
delete *vit;
}
}
}
}
return ok;
}
void p3GxsCircles::createGroup(uint32_t& token, RsGxsCircleGroup &group)
{
#ifdef DEBUG_CIRCLES
@ -2065,21 +2133,3 @@ bool p3GxsCircles::processMembershipRequests(uint32_t token)
return true ;
}

View File

@ -199,6 +199,7 @@ virtual RsServiceInfo getServiceInfo();
virtual bool getGroupData(const uint32_t &token, std::vector<RsGxsCircleGroup> &groups);
virtual bool getMsgData(const uint32_t &token, std::vector<RsGxsCircleMsg> &msgs);
virtual void createGroup(uint32_t& token, RsGxsCircleGroup &group);
virtual void updateGroup(uint32_t &token, RsGxsCircleGroup &group);

View File

@ -44,8 +44,6 @@
RsGxsForums *rsGxsForums = NULL;
const uint32_t GXSFORUMS_MSG_STORE_PERIOD = 60*60*24*31*12; // 12 months / 1 year
#define FORUM_TESTEVENT_DUMMYDATA 0x0001
#define DUMMYDATA_PERIOD 60 // long enough for some RsIdentities to be generated.
@ -56,8 +54,7 @@ const uint32_t GXSFORUMS_MSG_STORE_PERIOD = 60*60*24*31*12; // 12 months / 1 yea
p3GxsForums::p3GxsForums( RsGeneralDataService *gds,
RsNetworkExchangeService *nes, RsGixs* gixs ) :
RsGenExchange( gds, nes, new RsGxsForumSerialiser(),
RS_SERVICE_GXS_TYPE_FORUMS, gixs, forumsAuthenPolicy(),
GXSFORUMS_MSG_STORE_PERIOD),
RS_SERVICE_GXS_TYPE_FORUMS, gixs, forumsAuthenPolicy()),
RsGxsForums(this), mGenToken(0), mGenActive(false), mGenCount(0)
{
// Test Data disabled in Repo.

View File

@ -4397,32 +4397,31 @@ void p3IdService::handleResponse(uint32_t token, uint32_t req_type)
// stuff.
switch(req_type)
{
case GXSIDREQ_CACHEOWNIDS:
cache_load_ownids(token);
break;
case GXSIDREQ_CACHELOAD:
cache_load_for_token(token);
break;
case GXSIDREQ_PGPHASH:
pgphash_handlerequest(token);
break;
case GXSIDREQ_RECOGN:
recogn_handlerequest(token);
break;
case GXSIDREQ_CACHETEST:
cachetest_handlerequest(token);
break;
case GXSIDREQ_OPINION:
opinion_handlerequest(token);
break;
case GXSIDREQ_SERIALIZE_TO_MEMORY:
handle_get_serialized_grp(token) ;
default:
/* error */
std::cerr << "p3IdService::handleResponse() Unknown Request Type: " << req_type;
std::cerr << std::endl;
break;
case GXSIDREQ_CACHEOWNIDS:
cache_load_ownids(token);
break;
case GXSIDREQ_CACHELOAD:
cache_load_for_token(token);
break;
case GXSIDREQ_PGPHASH:
pgphash_handlerequest(token);
break;
case GXSIDREQ_RECOGN:
recogn_handlerequest(token);
break;
case GXSIDREQ_CACHETEST:
cachetest_handlerequest(token);
break;
case GXSIDREQ_OPINION:
opinion_handlerequest(token);
break;
case GXSIDREQ_SERIALIZE_TO_MEMORY:
handle_get_serialized_grp(token);
break;
default:
std::cerr << "p3IdService::handleResponse() Unknown Request Type: "
<< req_type << std::endl;
break;
}
}

View File

@ -51,7 +51,7 @@ together. The routers will talk to a fake link manager, which reports the peers
Required components:
===================
NetworkGraph: a set of friends, with connexions. Should be able to be saved to a file for debugging.
NetworkGraph: a set of friends, with connections. Should be able to be saved to a file for debugging.
GraphNode: a RS peer, represented by a random SSL id, a link manager, and possibly components such as file transfer, etc.

View File

@ -179,6 +179,7 @@ void RsThread::start(const std::string &threadName)
THREAD_DEBUG << "pqithreadstreamer::start() initing should_stop=0" << std::endl;
#endif
mShouldStopSemaphore.set(0) ;
mHasStoppedSemaphore.set(0) ;
int err ;

View File

@ -45,16 +45,11 @@ int main(int argc, char *argv[])
dynamic_cast<resource_api::ResourceRouter*>(&ctrl_mod),
&resource_api::RsControlModule::handleRequest);
#if defined(Q_OS_WIN) && defined(QT_DEBUG)
QString sockPath = "RS/";
#elif defined(Q_OS_WIN)
QString sockPath = QCoreApplication::applicationDirPath();
#else
QString sockPath = QDir::homePath() + "/.retroshare";
#endif
QString sockPath = QDir::homePath() + "/.retroshare";
sockPath.append("/libresapi.sock");
qDebug() << "Listening on:" << sockPath;
ApiServerLocal apiServerLocal(&api, sockPath); (void) apiServerLocal;
while (!ctrl_mod.processShouldExit())

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>1048</width>
<height>779</height>
<width>1573</width>
<height>1177</height>
</rect>
</property>
<property name="sizePolicy">
@ -283,8 +283,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>717</width>
<height>692</height>
<width>1372</width>
<height>1000</height>
</rect>
</property>
<layout class="QVBoxLayout" name="scrollAreaWidgetContentsVLayout">
@ -569,8 +569,9 @@ border-image: url(:/images/closepressed.png)
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the average of your friend's opinions. If not, your own opinion gives the score.&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -0.6, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a higher reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 30 days). &lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;You can change the thresholds and the time of inactivity to delete identities in preferences -&amp;gt; people. &lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>

View File

@ -25,45 +25,43 @@
#include "NewsFeed.h"
#include "ui_NewsFeed.h"
#include <retroshare/rsnotify.h>
#include <retroshare/rspeers.h>
#include <retroshare/rsbanlist.h>
#include <retroshare/rsgxschannels.h>
#include <retroshare/rsgxsforums.h>
#include <retroshare/rsposted.h>
#include <retroshare/rsmsgs.h>
#include <retroshare/rsnotify.h>
#include <retroshare/rspeers.h>
#include <retroshare/rsplugin.h>
#include <retroshare/rsbanlist.h>
#include "feeds/GxsChannelGroupItem.h"
#include "feeds/GxsChannelPostItem.h"
#include "feeds/GxsForumGroupItem.h"
#include "feeds/GxsForumMsgItem.h"
#include "feeds/PostedGroupItem.h"
#include "Posted/PostedItem.h"
#include "feeds/GxsForumMsgItem.h"
#include "settings/rsettingswin.h"
#include <retroshare/rsposted.h>
#include "feeds/ChatMsgItem.h"
#ifdef BLOGS
#include "feeds/BlogNewItem.h"
#include "feeds/BlogMsgItem.h"
#endif
#include "feeds/GxsCircleItem.h"
#include "feeds/GxsChannelGroupItem.h"
#include "feeds/GxsChannelPostItem.h"
#include "feeds/GxsForumGroupItem.h"
#include "feeds/GxsForumMsgItem.h"
#include "feeds/MsgItem.h"
#include "feeds/NewsFeedUserNotify.h"
#include "feeds/PeerItem.h"
#include "feeds/ChatMsgItem.h"
#include "feeds/PostedGroupItem.h"
#include "feeds/SecurityItem.h"
#include "feeds/SecurityIpItem.h"
#include "feeds/NewsFeedUserNotify.h"
#include "settings/rsettingswin.h"
#include "settings/rsharesettings.h"
#include "chat/ChatDialog.h"
#include "Posted/PostedItem.h"
#include "msgs/MessageComposer.h"
#include "msgs/MessageInterface.h"
#include "common/FeedNotify.h"
#include "notifyqt.h"
#include "gui/msgs/MessageInterface.h"
const uint32_t NEWSFEED_PEERLIST = 0x0001;
const uint32_t NEWSFEED_FORUMNEWLIST = 0x0002;
@ -80,6 +78,7 @@ const uint32_t NEWSFEED_CHATMSGLIST = 0x0009;
const uint32_t NEWSFEED_SECLIST = 0x000a;
const uint32_t NEWSFEED_POSTEDNEWLIST = 0x000b;
const uint32_t NEWSFEED_POSTEDMSGLIST = 0x000c;
const uint32_t NEWSFEED_CIRCLELIST = 0x000d;
#define ROLE_RECEIVED FEED_TREEWIDGET_SORTROLE
@ -102,6 +101,7 @@ NewsFeed::NewsFeed(QWidget *parent) :
ui->setupUi(this);
mTokenQueueChannel = NULL;
mTokenQueueCircle = NULL;
mTokenQueueForum = NULL;
mTokenQueuePosted = NULL;
@ -156,6 +156,9 @@ NewsFeed::~NewsFeed()
if (mTokenQueueChannel) {
delete(mTokenQueueChannel);
}
if (mTokenQueueCircle) {
delete(mTokenQueueCircle);
}
if (mTokenQueueForum) {
delete(mTokenQueueForum);
}
@ -226,7 +229,7 @@ void NewsFeed::updateDisplay()
addFeedItemPeerNew(fi);
break;
case RS_FEED_ITEM_PEER_OFFSET:
if (flags & RS_FEED_TYPE_PEER)
//if (flags & RS_FEED_TYPE_PEER) //Always allow this feed even if Friend notify is disabled.
addFeedItemPeerOffset(fi);
break;
@ -370,6 +373,52 @@ void NewsFeed::updateDisplay()
if (flags & RS_FEED_TYPE_FILES)
addFeedItemFilesNew(fi);
break;
case RS_FEED_ITEM_CIRCLE_MEMB_REQ:
if (flags & RS_FEED_TYPE_CIRCLE)
{
if (!mTokenQueueCircle) {
mTokenQueueCircle = new TokenQueue(rsGxsCircles->getTokenService(), instance);
}
RsGxsGroupId grpId(fi.mId1);
RsGxsMessageId msgId(fi.mId2);
if (!grpId.isNull() && !msgId.isNull()) {
RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
GxsMsgReq msgIds;
std::vector<RsGxsMessageId> &vect_msgIds = msgIds[grpId];
vect_msgIds.push_back(msgId);
uint32_t token;
mTokenQueueCircle->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, TOKEN_TYPE_MESSAGE);
}
}
// addFeedItemCircleMembReq(fi);
break;
case RS_FEED_ITEM_CIRCLE_INVIT_REC:
if (flags & RS_FEED_TYPE_CIRCLE)
{
if (!mTokenQueueCircle) {
mTokenQueueCircle = new TokenQueue(rsGxsCircles->getTokenService(), instance);
}
RsGxsGroupId grpId(fi.mId1);
if (!grpId.isNull()) {
RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
std::list<RsGxsGroupId> grpIds;
grpIds.push_back(grpId);
uint32_t token;
mTokenQueueCircle->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, grpIds, TOKEN_TYPE_GROUP);
}
}
// addFeedItemCircleInvitRec(fi);
break;
default:
std::cerr << "(EE) Unknown type " << std::hex << fi.mType << std::dec << " in news feed." << std::endl;
break;
@ -534,6 +583,24 @@ void NewsFeed::testFeeds(uint notifyFlags)
// not used
// instance->addFeedItemFilesNew(fi);
break;
case RS_FEED_TYPE_CIRCLE:
{
if (!instance->mTokenQueueCircle) {
instance->mTokenQueueCircle = new TokenQueue(rsGxsCircles->getTokenService(), instance);
}
RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
uint32_t token;
instance->mTokenQueueCircle->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, TOKEN_TYPE_GROUP);
break;
}
// instance->addFeedItemCircleMembReq(fi);
// instance->addFeedItemCircleInvitRec(fi);
break;
}
}
@ -542,6 +609,78 @@ void NewsFeed::testFeeds(uint notifyFlags)
instance->sendNewsFeedChanged();
}
void NewsFeed::loadCircleGroup(const uint32_t &token)
{
std::vector<RsGxsCircleGroup> groups;
if (!rsGxsCircles->getGroupData(token, groups)) {
std::cerr << "NewsFeed::loadCircleGroup() ERROR getting data";
std::cerr << std::endl;
return;
}
std::list<RsGxsId> own_identities;
rsIdentity->getOwnIds(own_identities);
std::vector<RsGxsCircleGroup>::const_iterator circleIt;
for (circleIt = groups.begin(); circleIt != groups.end(); ++circleIt) {
RsGxsCircleGroup group = *(circleIt);
RsGxsCircleDetails details;
if(rsGxsCircles->getCircleDetails(group.mMeta.mCircleId,details))
{
for(std::list<RsGxsId>::const_iterator it(own_identities.begin());it!=own_identities.end();++it) {
std::map<RsGxsId,uint32_t>::const_iterator vit = details.mSubscriptionFlags.find(*it);
uint32_t subscribe_flags = (vit == details.mSubscriptionFlags.end())?0:(vit->second);
if( !(subscribe_flags & GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED)
&& (subscribe_flags & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST) ) {
RsFeedItem fi;
fi.mId1 = group.mMeta.mGroupId.toStdString();
fi.mId2 = it->toStdString();
instance->addFeedItemCircleInvitRec(fi);
}
}
}
}
}
void NewsFeed::loadCircleMessage(const uint32_t &token)
{
std::vector<RsGxsCircleMsg> msgs;
if (!rsGxsCircles->getMsgData(token, msgs)) {
std::cerr << "NewsFeed::loadCircleMessage() ERROR getting data";
std::cerr << std::endl;
return;
}
std::list<RsGxsId> own_identities;
rsIdentity->getOwnIds(own_identities);
std::vector<RsGxsCircleMsg>::iterator msgIt;
for (msgIt = msgs.begin(); msgIt != msgs.end(); ++msgIt) {
RsGxsCircleMsg msg = *(msgIt);
RsGxsCircleDetails details;
if(rsGxsCircles->getCircleDetails(RsGxsCircleId(msg.mMeta.mGroupId),details)) {
//for(std::list<RsGxsId>::const_iterator it(own_identities.begin());it!=own_identities.end();++it) {
// std::map<RsGxsId,uint32_t>::const_iterator vit = details.mSubscriptionFlags.find(*it);
// if (vit != details.mSubscriptionFlags.end()) {
RsFeedItem fi;
fi.mId1 = msgIt->mMeta.mGroupId.toStdString();
fi.mId2 = msgIt->mMeta.mAuthorId.toStdString();
if (msgIt->stuff == "SUBSCRIPTION_REQUEST_UNSUBSCRIBE")
instance->remFeedItemCircleMembReq(fi);
else
instance->addFeedItemCircleMembReq(fi);
//}
//}
}
}
}
void NewsFeed::loadChannelGroup(const uint32_t &token)
{
std::vector<RsGxsChannelGroup> groups;
@ -821,7 +960,24 @@ void NewsFeed::loadRequest(const TokenQueue *queue, const TokenRequest &req)
break;
default:
std::cerr << "NewsFeed::loadRequest() ERROR: INVALID TYPE";
std::cerr << "NewsFeed::loadRequest() ERROR: INVALID CHANNEL TYPE";
std::cerr << std::endl;
break;
}
}
if (queue == mTokenQueueCircle) {
switch (req.mUserType) {
case TOKEN_TYPE_GROUP:
loadCircleGroup(req.mToken);
break;
case TOKEN_TYPE_MESSAGE:
loadCircleMessage(req.mToken);
break;
default:
std::cerr << "NewsFeed::loadRequest() ERROR: INVALID CIRCLE TYPE";
std::cerr << std::endl;
break;
}
@ -842,7 +998,7 @@ void NewsFeed::loadRequest(const TokenQueue *queue, const TokenRequest &req)
break;
default:
std::cerr << "NewsFeed::loadRequest() ERROR: INVALID TYPE";
std::cerr << "NewsFeed::loadRequest() ERROR: INVALID FORUM TYPE";
std::cerr << std::endl;
break;
}
@ -859,7 +1015,7 @@ void NewsFeed::loadRequest(const TokenQueue *queue, const TokenRequest &req)
break;
default:
std::cerr << "NewsFeed::loadRequest() ERROR: INVALID TYPE";
std::cerr << "NewsFeed::loadRequest() ERROR: INVALID POSTED TYPE";
std::cerr << std::endl;
break;
}
@ -908,18 +1064,24 @@ void NewsFeed::addFeedItem(FeedItem *item)
struct AddFeedItemIfUniqueData
{
AddFeedItemIfUniqueData(FeedItem *feedItem, int type, const RsPeerId &sslId, const std::string& ipAddr, const std::string& ipAddrReported)
: mType(type), mSslId(sslId), mIpAddr(ipAddr), mIpAddrReported(ipAddrReported)
AddFeedItemIfUniqueData(FeedItem *feedItem, int type
, const std::string& id1, const std::string& id2
, const std::string& id3, const std::string& id4)
: mType(type), mId1(id1), mId2(id2), mId3(id3), mId4(id4)
{
mGxsCircleItem = dynamic_cast<GxsCircleItem*>(feedItem);
mPeerItem = dynamic_cast<PeerItem*>(feedItem);
mSecItem = dynamic_cast<SecurityItem*>(feedItem);
mSecurityIpItem = dynamic_cast<SecurityIpItem*>(feedItem);
}
int mType;
const RsPeerId &mSslId;
const std::string& mIpAddr;
const std::string& mIpAddrReported;
const std::string& mId1;
const std::string& mId2;
const std::string& mId3;
const std::string& mId4;
GxsCircleItem *mGxsCircleItem;
PeerItem *mPeerItem;
SecurityItem *mSecItem;
SecurityIpItem *mSecurityIpItem;
@ -928,13 +1090,21 @@ struct AddFeedItemIfUniqueData
static bool addFeedItemIfUniqueCallback(FeedItem *feedItem, void *data)
{
AddFeedItemIfUniqueData *findData = (AddFeedItemIfUniqueData*) data;
if (!findData || findData->mSslId.isNull()) {
if (!findData || findData->mId1.empty()) {
return false;
}
if (findData->mGxsCircleItem) {
GxsCircleItem *gxsCircleItem = dynamic_cast<GxsCircleItem*>(feedItem);
if (gxsCircleItem && gxsCircleItem->isSame(RsGxsCircleId(findData->mId1), RsGxsId(findData->mId2), findData->mType)) {
return true;
}
return false;
}
if (findData->mPeerItem) {
PeerItem *peerItem = dynamic_cast<PeerItem*>(feedItem);
if (peerItem && peerItem->isSame(findData->mSslId, findData->mType)) {
if (peerItem && peerItem->isSame(RsPeerId(findData->mId1), findData->mType)) {
return true;
}
return false;
@ -942,7 +1112,7 @@ static bool addFeedItemIfUniqueCallback(FeedItem *feedItem, void *data)
if (findData->mSecItem) {
SecurityItem *secitem = dynamic_cast<SecurityItem*>(feedItem);
if (secitem && secitem->isSame(findData->mSslId, findData->mType)) {
if (secitem && secitem->isSame(RsPeerId(findData->mId1), findData->mType)) {
return true;
}
return false;
@ -950,7 +1120,7 @@ static bool addFeedItemIfUniqueCallback(FeedItem *feedItem, void *data)
if (findData->mSecurityIpItem) {
SecurityIpItem *securityIpItem = dynamic_cast<SecurityIpItem*>(feedItem);
if (securityIpItem && securityIpItem->isSame(findData->mIpAddr, findData->mIpAddrReported, findData->mType)) {
if (securityIpItem && securityIpItem->isSame(findData->mId1, findData->mId2, findData->mType)) {
return true;
}
return false;
@ -959,9 +1129,9 @@ static bool addFeedItemIfUniqueCallback(FeedItem *feedItem, void *data)
return false;
}
void NewsFeed::addFeedItemIfUnique(FeedItem *item, int itemType, const RsPeerId &sslId, const std::string& ipAddr, const std::string& ipAddrReported, bool replace)
void NewsFeed::addFeedItemIfUnique(FeedItem *item, int itemType, const std::string& id1, const std::string& id2, const std::string& id3, const std::string& id4, bool replace)
{
AddFeedItemIfUniqueData data(item, itemType, sslId, ipAddr, ipAddrReported);
AddFeedItemIfUniqueData data(item, itemType, id1, id2, id3, id4);
FeedItem *feedItem = ui->feedWidget->findFeedItem(addFeedItemIfUniqueCallback, &data);
if (feedItem) {
@ -976,6 +1146,18 @@ void NewsFeed::addFeedItemIfUnique(FeedItem *item, int itemType, const RsPeerId
addFeedItem(item);
}
void NewsFeed::remUniqueFeedItem(FeedItem *item, int itemType, const std::string &id1, const std::string &id2, const std::string &id3, const std::string &id4)
{
AddFeedItemIfUniqueData data(item, itemType, id1, id2, id3, id4);
FeedItem *feedItem = ui->feedWidget->findFeedItem(addFeedItemIfUniqueCallback, &data);
if (feedItem) {
delete item;
ui->feedWidget->removeFeedItem(feedItem);
}
}
void NewsFeed::addFeedItemPeerConnect(const RsFeedItem &fi)
{
/* make new widget */
@ -1038,7 +1220,7 @@ void NewsFeed::addFeedItemPeerOffset(const RsFeedItem &fi)
PeerItem *pi = new PeerItem(this, NEWSFEED_PEERLIST, RsPeerId(fi.mId1), PEER_TYPE_OFFSET, false);
/* add to layout */
addFeedItemIfUnique(pi, PEER_TYPE_OFFSET, RsPeerId(fi.mId1), "", "", false);
addFeedItemIfUnique(pi, PEER_TYPE_OFFSET, fi.mId1, fi.mId2, fi.mId3, fi.mId4, false);
#ifdef NEWS_DEBUG
std::cerr << "NewsFeed::addFeedItemPeerOffset()";
@ -1052,7 +1234,7 @@ void NewsFeed::addFeedItemSecurityConnectAttempt(const RsFeedItem &fi)
SecurityItem *pi = new SecurityItem(this, NEWSFEED_SECLIST, RsPgpId(fi.mId1), RsPeerId(fi.mId2), fi.mId3, fi.mId4, fi.mType, false);
/* add to layout */
addFeedItemIfUnique(pi, fi.mType, RsPeerId(fi.mId2), "", "", false);
addFeedItemIfUnique(pi, fi.mType, fi.mId2, "", "", "", false);
#ifdef NEWS_DEBUG
std::cerr << "NewsFeed::addFeedItemSecurityConnectAttempt()";
@ -1066,7 +1248,7 @@ void NewsFeed::addFeedItemSecurityAuthDenied(const RsFeedItem &fi)
SecurityItem *pi = new SecurityItem(this, NEWSFEED_SECLIST, RsPgpId(fi.mId1), RsPeerId(fi.mId2), fi.mId3, fi.mId4, fi.mType, false);
/* add to layout */
addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_AUTH_DENIED, RsPeerId(fi.mId2), "", "", false);
addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_AUTH_DENIED, fi.mId2, "", "", "", false);
#ifdef NEWS_DEBUG
std::cerr << "NewsFeed::addFeedItemSecurityAuthDenied()";
@ -1080,7 +1262,7 @@ void NewsFeed::addFeedItemSecurityUnknownIn(const RsFeedItem &fi)
SecurityItem *pi = new SecurityItem(this, NEWSFEED_SECLIST, RsPgpId(fi.mId1), RsPeerId(fi.mId2), fi.mId3, fi.mId4, RS_FEED_ITEM_SEC_UNKNOWN_IN, false);
/* add to layout */
addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_UNKNOWN_IN, RsPeerId(fi.mId2), "", "", false);
addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_UNKNOWN_IN, fi.mId2, "", "", "", false);
#ifdef NEWS_DEBUG
std::cerr << "NewsFeed::addFeedItemSecurityUnknownIn()";
@ -1094,7 +1276,7 @@ void NewsFeed::addFeedItemSecurityUnknownOut(const RsFeedItem &fi)
SecurityItem *pi = new SecurityItem(this, NEWSFEED_SECLIST, RsPgpId(fi.mId1), RsPeerId(fi.mId2), fi.mId3, fi.mId4, RS_FEED_ITEM_SEC_UNKNOWN_OUT, false);
/* add to layout */
addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_UNKNOWN_OUT, RsPeerId(fi.mId2), "", "", false);
addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_UNKNOWN_OUT, fi.mId2, "", "", "", false);
#ifdef NEWS_DEBUG
std::cerr << "NewsFeed::addFeedItemSecurityUnknownOut()";
@ -1108,7 +1290,7 @@ void NewsFeed::addFeedItemSecurityIpBlacklisted(const RsFeedItem &fi, bool isTes
SecurityIpItem *pi = new SecurityIpItem(this, RsPeerId(fi.mId1), fi.mId2, fi.mResult1, RS_FEED_ITEM_SEC_IP_BLACKLISTED, isTest);
/* add to layout */
addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_IP_BLACKLISTED, RsPeerId(fi.mId1), fi.mId2, "", false);
addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_IP_BLACKLISTED, fi.mId1, fi.mId2, fi.mId3, fi.mId4, false);
#ifdef NEWS_DEBUG
std::cerr << "NewsFeed::addFeedItemSecurityIpBlacklisted()";
@ -1122,7 +1304,7 @@ void NewsFeed::addFeedItemSecurityWrongExternalIpReported(const RsFeedItem &fi,
SecurityIpItem *pi = new SecurityIpItem(this, RsPeerId(fi.mId1), fi.mId2, fi.mId3, RS_FEED_ITEM_SEC_IP_WRONG_EXTERNAL_IP_REPORTED, isTest);
/* add to layout */
addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_IP_WRONG_EXTERNAL_IP_REPORTED, RsPeerId(fi.mId1), fi.mId2, fi.mId3, false);
addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_IP_WRONG_EXTERNAL_IP_REPORTED, fi.mId1, fi.mId2, fi.mId3, fi.mId4, false);
#ifdef NEWS_DEBUG
std::cerr << "NewsFeed::addFeedItemSecurityWrongExternalIpReported()";
@ -1375,6 +1557,66 @@ void NewsFeed::addFeedItemFilesNew(const RsFeedItem &/*fi*/)
#endif
}
void NewsFeed::addFeedItemCircleMembReq(const RsFeedItem &fi)
{
RsGxsCircleId circleId(fi.mId1);
RsGxsId gxsId(fi.mId2);
if (circleId.isNull() || gxsId.isNull()) {
return;
}
/* make new widget */
GxsCircleItem *item = new GxsCircleItem(this, NEWSFEED_CIRCLELIST, circleId, gxsId, RS_FEED_ITEM_CIRCLE_MEMB_REQ);
/* add to layout */
addFeedItemIfUnique(item, RS_FEED_ITEM_CIRCLE_MEMB_REQ, fi.mId1, fi.mId2, fi.mId3, fi.mId4, false);
#ifdef NEWS_DEBUG
std::cerr << "NewsFeed::addFeedItemCircleMembReq()" << std::endl;
#endif
}
void NewsFeed::remFeedItemCircleMembReq(const RsFeedItem &fi)
{
RsGxsCircleId circleId(fi.mId1);
RsGxsId gxsId(fi.mId2);
if (circleId.isNull() || gxsId.isNull()) {
return;
}
/* make new widget */
GxsCircleItem *item = new GxsCircleItem(this, NEWSFEED_CIRCLELIST, circleId, gxsId, RS_FEED_ITEM_CIRCLE_MEMB_REQ);
/* add to layout */
remUniqueFeedItem(item, RS_FEED_ITEM_CIRCLE_MEMB_REQ, fi.mId1, fi.mId2, fi.mId3, fi.mId4);
#ifdef NEWS_DEBUG
std::cerr << "NewsFeed::remFeedItemCircleMembReq()" << std::endl;
#endif
}
void NewsFeed::addFeedItemCircleInvitRec(const RsFeedItem &fi)
{
RsGxsCircleId circleId(fi.mId1);
RsGxsId gxsId(fi.mId2);
if (circleId.isNull()) {
return;
}
/* make new widget */
GxsCircleItem *item = new GxsCircleItem(this, NEWSFEED_CIRCLELIST, circleId, gxsId, RS_FEED_ITEM_CIRCLE_INVIT_REC);
/* add to layout */
addFeedItem(item);
#ifdef NEWS_DEBUG
std::cerr << "NewsFeed::addFeedItemCircleInvitRec()" << std::endl;
#endif
}
/* FeedHolder Functions (for FeedItem functionality) */
QScrollArea *NewsFeed::getScrollArea()
{
@ -1403,7 +1645,7 @@ void NewsFeed::openChat(const RsPeerId &peerId)
ChatDialog::chatFriend(ChatId(peerId));
}
void NewsFeed::openComments(uint32_t /*type*/, const RsGxsGroupId &/*groupId*/, const QVector<RsGxsMessageId>& versions,const RsGxsMessageId &/*msgId*/, const QString &/*title*/)
void NewsFeed::openComments(uint32_t /*type*/, const RsGxsGroupId &/*groupId*/, const QVector<RsGxsMessageId> &/*versions*/,const RsGxsMessageId &/*msgId*/, const QString &/*title*/)
{
std::cerr << "NewsFeed::openComments() Not Handled Yet";
std::cerr << std::endl;

View File

@ -83,7 +83,8 @@ private slots:
private:
void addFeedItem(FeedItem *item);
void addFeedItemIfUnique(FeedItem *item, int itemType, const RsPeerId &sslId, const std::string& ipAddr, const std::string& ipAddrReported, bool replace);
void addFeedItemIfUnique(FeedItem *item, int itemType, const std::string& id1, const std::string& id2, const std::string& id3, const std::string& id4, bool replace);
void remUniqueFeedItem(FeedItem *item, int itemType, const std::string& id1, const std::string& id2, const std::string& id3, const std::string& id4);
void addFeedItemPeerConnect(const RsFeedItem &fi);
void addFeedItemPeerDisconnect(const RsFeedItem &fi);
@ -119,6 +120,10 @@ private:
void addFeedItemMessage(const RsFeedItem &fi);
void addFeedItemFilesNew(const RsFeedItem &fi);
void addFeedItemCircleMembReq(const RsFeedItem &fi);
void remFeedItemCircleMembReq(const RsFeedItem &fi);
void addFeedItemCircleInvitRec(const RsFeedItem &fi);
virtual void loadChannelGroup(const uint32_t &token);
virtual void loadChannelPost(const uint32_t &token);
virtual void loadChannelPublishKey(const uint32_t &token);
@ -130,8 +135,12 @@ private:
virtual void loadPostedGroup(const uint32_t &token);
virtual void loadPostedMessage(const uint32_t &token);
virtual void loadCircleGroup(const uint32_t &token);
virtual void loadCircleMessage(const uint32_t &token);
private:
TokenQueue *mTokenQueueChannel;
TokenQueue *mTokenQueueCircle;
TokenQueue *mTokenQueueForum;
TokenQueue *mTokenQueuePosted;

View File

@ -1275,8 +1275,10 @@ static void processList(const QStringList &list, const QString &textSingular, co
/* make path for downloaded file */
std::string path;
path = fi.path;//Shared files has path with filename included
if (fi.downloadStatus == FT_STATE_COMPLETE)
path = fi.path + "/" + fi.fname;
//Seems that all FileInfo get .path==filepath+filename
//if (fi.downloadStatus == FT_STATE_COMPLETE)
// path = fi.path + "/" + fi.fname;
QFileInfo qinfo;
qinfo.setFile(QString::fromUtf8(path.c_str()));

View File

@ -44,7 +44,7 @@ void AvatarDefs::getOwnAvatar(QPixmap &avatar, const QString& defaultImage)
/* load image */
avatar.loadFromData(data, size, "PNG") ;
delete[] data;
free(data);
}
void AvatarDefs::getAvatarFromSslId(const RsPeerId& sslId, QPixmap &avatar, const QString& defaultImage)
{
@ -61,7 +61,7 @@ void AvatarDefs::getAvatarFromSslId(const RsPeerId& sslId, QPixmap &avatar, cons
/* load image */
avatar.loadFromData(data, size, "PNG") ;
delete[] data;
free(data);
}
void AvatarDefs::getAvatarFromGxsId(const RsGxsId& gxsId, QPixmap &avatar, const QString& defaultImage)
{
@ -112,5 +112,5 @@ void AvatarDefs::getAvatarFromGpgId(const RsPgpId& gpgId, QPixmap &avatar, const
/* load image */
avatar.loadFromData(data, size, "PNG") ;
delete[] data;
free(data);
}

View File

@ -27,6 +27,7 @@
#include <iostream>
#include <retroshare/rspeers.h>
#include <gui/common/GroupDefs.h>
/** Constructor */
GroupChooser::GroupChooser(QWidget *parent)
@ -51,7 +52,7 @@ bool GroupChooser::makeNodeGroupDesc(const RsGroupInfo& info, QString &desc)
if(info.name.empty())
desc = tr("[Unknown]") ;
else
desc = "\"" + QString::fromUtf8(info.name.c_str()) + "\"";
desc = "\"" + GroupDefs::name(info) + "\"";
desc += " [" ;
desc += QString::fromStdString(info.id.toStdString().substr(0,3));
@ -88,7 +89,7 @@ void GroupChooser::loadGroups()
std::cerr << std::endl;
continue;
}
QString id = QString::fromStdString(it->id.toStdString());
QString id = QString::fromStdString((*it).id.toStdString()) ;
addItem(str, id);

View File

@ -323,15 +323,6 @@ RSGraphWidget::resetGraph()
updateIfPossible();
}
/** Toggles display of respective graph lines and counters. */
//void
//DhtGraph::setShowCounters(bool showRSDHT, bool showALLDHT)
//{
// _showRSDHT = showRSDHT;
// _showALLDHT = showALLDHT;
// this->update();
//}
/** Overloads default QWidget::paintEvent. Draws the actual
* bandwidth graph. */
void RSGraphWidget::paintEvent(QPaintEvent *)
@ -354,9 +345,11 @@ void RSGraphWidget::paintEvent(QPaintEvent *)
/* Paint the scale */
paintScale1();
/* Plot the rsDHT/allDHT data */
/* Plot the data */
paintData();
/* Paint the rsDHT/allDHT totals */
/* Paint the totals */
paintTotals();
// part of the scale that needs to write over the data curves.
@ -427,17 +420,19 @@ void RSGraphWidget::paintData()
QColor pcolor = getColor(source.displayName(i).toStdString()) ;
/* Plot the bandwidth data as area graphs */
if (_flags & RSGRAPH_FLAGS_PAINT_STYLE_PLAIN)
paintIntegral(points, pcolor, _opacity);
/* Plot the bandwidth as solid lines. If the graph style is currently an
* area graph, we end up outlining the integrals. */
/* Plot the bandwidth as solid lines. If the graph style is currently an area graph, we end up outlining the integrals. */
if(_flags & RSGRAPH_FLAGS_PAINT_STYLE_DOTS)
paintDots(points, pcolor);
else
paintLine(points, pcolor);
/* Plot the data as area graphs */
points.push_front(QPointF( _rec.width(), _rec.height() - _graph_base)) ; // add a point in the lower right corner, to close the path.
if (_flags & RSGRAPH_FLAGS_PAINT_STYLE_PLAIN)
paintIntegral(points, pcolor, _opacity);
}
if(_maxValue > 0.0f)
{
@ -520,7 +515,7 @@ void RSGraphWidget::pointsFromData(const std::vector<QPointF>& values,QVector<QP
points << QPointF(px,py) ;
if(!(_flags & RSGRAPH_FLAGS_PAINT_STYLE_DOTS) && (i==values.size()-1))
points << QPointF(px,y) ;
points << QPointF(px,py) ;
last_px = px ;
last_py = py ;

View File

@ -19,13 +19,15 @@
* Boston, MA 02110-1301, USA.
****************************************************************/
#include <QUrl>
#include <QDesktopServices>
#include <QMessageBox>
#include <QCheckBox>
#include <QClipboard>
#include <QDesktopServices>
#include <QFileDialog>
#include <QTextStream>
#include <QLayout>
#include <QMessageBox>
#include <QTextCodec>
#include <QTextStream>
#include <QUrl>
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <QUrlQuery>
@ -107,7 +109,7 @@ ConnectFriendWizard::ConnectFriendWizard(QWidget *parent) :
ui->foffRadioButton->hide();
ui->rsidRadioButton->hide();
ui->fr_label->hide();
ui->cp_Label->hide();
ui->requestinfolabel->hide();
connect(ui->acceptNoSignGPGCheckBox,SIGNAL(toggled(bool)), ui->_options_GB,SLOT(setEnabled(bool))) ;
@ -135,7 +137,7 @@ ConnectFriendWizard::ConnectFriendWizard(QWidget *parent) :
else
{
ui->userFrame->hide(); // certificates page - top half with own cert and it's functions
ui->horizontalLayout_13->hide(); // Advanced options - key sign, whitelist, direct source ...
ui->cp_Frame->hide(); // Advanced options - key sign, whitelist, direct source ...
AdvancedVisible=false;
ui->trustLabel->hide();
ui->trustEdit->hide();
@ -145,7 +147,25 @@ ConnectFriendWizard::ConnectFriendWizard(QWidget *parent) :
rsPeers->getPeerCount (&friendCount, &onlineCount, false);
if(friendCount<30)
ui->makefriend_infolabel->hide();
//Add warning to direct source checkbox depends general setting.
switch (rsFiles->filePermDirectDL())
{
case RS_FILE_PERM_DIRECT_DL_YES:
ui->_direct_transfer_CB->setIcon(QIcon(":/icons/warning_yellow_128.png"));
ui->_direct_transfer_CB->setToolTip(ui->_direct_transfer_CB->toolTip().append(tr("\nWarning: In your File-Transfer option, you select allow direct download to Yes.")));
ui->_direct_transfer_CB_2->setIcon(QIcon(":/icons/warning_yellow_128.png"));
ui->_direct_transfer_CB_2->setToolTip(ui->_direct_transfer_CB_2->toolTip().append(tr("\nWarning: In your File-Transfer option, you select allow direct download to Yes.")));
break ;
case RS_FILE_PERM_DIRECT_DL_NO:
ui->_direct_transfer_CB->setIcon(QIcon(":/icons/warning_yellow_128.png"));
ui->_direct_transfer_CB->setToolTip(ui->_direct_transfer_CB->toolTip().append(tr("\nWarning: In your File-Transfer option, you select allow direct download to No.")));
ui->_direct_transfer_CB_2->setIcon(QIcon(":/icons/warning_yellow_128.png"));
ui->_direct_transfer_CB_2->setToolTip(ui->_direct_transfer_CB_2->toolTip().append(tr("\nWarning: In your File-Transfer option, you select allow direct download to No.")));
break ;
default: break ;
}
updateStylesheet();
}
@ -279,7 +299,7 @@ void ConnectFriendWizard::setCertificate(const QString &certificate, bool friend
//setStartId(friendRequest ? Page_FriendRequest : Page_Conclusion);
setStartId(Page_Conclusion);
if (friendRequest){
ui->fr_label->show();
ui->cp_Label->show();
ui->requestinfolabel->show();
setTitleText(ui->ConclusionPage, tr("Friend request"));
ui->ConclusionPage->setSubTitle(tr("Details about the request"));
@ -305,7 +325,7 @@ void ConnectFriendWizard::setGpgId(const RsPgpId &gpgId, const RsPeerId &sslId,
//setStartId(friendRequest ? Page_FriendRequest : Page_Conclusion);
setStartId(Page_Conclusion);
if (friendRequest){
ui->fr_label->show();
ui->cp_Label->show();
ui->requestinfolabel->show();
setTitleText(ui->ConclusionPage,tr("Friend request"));
ui->ConclusionPage->setSubTitle(tr("Details about the request"));
@ -520,7 +540,7 @@ void ConnectFriendWizard::initializePage(int id)
}
}
ui->fr_label->setText(tr("You have a friend request from") + " " + QString::fromUtf8(peerDetails.name.c_str()));
ui->cp_Label->setText(tr("You have a friend request from") + " " + QString::fromUtf8(peerDetails.name.c_str()));
ui->nameEdit->setText(QString::fromUtf8(peerDetails.name.c_str()));
ui->trustEdit->setText(trustString);
ui->emailEdit->setText(QString::fromUtf8(peerDetails.email.c_str()));
@ -619,7 +639,7 @@ void ConnectFriendWizard::initializePage(int id)
ui->fr_nodeEdit->setText(loc);
ui->fr_label_3->setText(tr("You have a friend request from") + " " + QString::fromUtf8(peerDetails.name.c_str()));
ui->fr_InfoTopLabel->setText(tr("You have a friend request from") + " " + QString::fromUtf8(peerDetails.name.c_str()));
fillGroups(this, ui->fr_groupComboBox, groupId);
}
@ -1345,13 +1365,13 @@ void ConnectFriendWizard::toggleAdvanced()
{
if(AdvancedVisible)
{
ui->horizontalLayout_13->hide();
ui->cp_Frame->hide();
ui->toggleadvancedButton->setText("Show advanced options");
AdvancedVisible=false;
}
else
{
ui->horizontalLayout_13->show();
ui->cp_Frame->show();
ui->toggleadvancedButton->setText("Hide advanced options");
AdvancedVisible=true;
}

View File

@ -27,7 +27,7 @@
<attribute name="pageId">
<string notr="true">ConnectFriendWizard::Page_Intro</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QVBoxLayout" name="IntroPageVLayout">
<item>
<widget class="QRadioButton" name="textRadioButton">
<property name="text">
@ -90,12 +90,12 @@
<attribute name="pageId">
<string notr="true">ConnectFriendWizard::Page_Text</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_4">
<layout class="QVBoxLayout" name="TextPageVLayout">
<item>
<widget class="QFrame" name="userFrame">
<layout class="QGridLayout" name="gridLayout_2">
<layout class="QGridLayout" name="userFrameGLayout">
<item row="1" column="1">
<layout class="QVBoxLayout" name="verticalLayout_2">
<layout class="QVBoxLayout" name="userCertButtonVLayout">
<item>
<widget class="QToolButton" name="userCertHelpButton">
<property name="sizePolicy">
@ -235,7 +235,7 @@
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<spacer name="userCertButtonVSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
@ -396,7 +396,7 @@
<attribute name="pageId">
<string notr="true">ConnectFriendWizard::Page_Cert</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_5">
<layout class="QVBoxLayout" name="CertificatePageVLayout">
<item>
<widget class="QGroupBox" name="userFileFrame">
<property name="title">
@ -405,7 +405,7 @@
<property name="flat">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<layout class="QHBoxLayout" name="userFileFrameHLayout">
<item>
<widget class="QLabel" name="userFileLabel">
<property name="text">
@ -434,7 +434,7 @@
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<layout class="QHBoxLayout" name="friendFileNameHLayout">
<item>
<widget class="DropLineEdit" name="friendFileNameEdit"/>
</item>
@ -459,9 +459,9 @@
<attribute name="pageId">
<string notr="true">ConnectFriendWizard::Page_Foff</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_11">
<layout class="QVBoxLayout" name="FofPageVLayout">
<item>
<widget class="QLabel" name="userFileLabel_2">
<widget class="QLabel" name="userSelectionLabel">
<property name="text">
<string>Show me:</string>
</property>
@ -506,7 +506,7 @@
<attribute name="pageId">
<string notr="true">ConnectFriendWizard::Page_Rsid</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_7">
<layout class="QVBoxLayout" name="RsidPageVLayout">
<item>
<widget class="QGroupBox" name="userRsidFrame">
<property name="title">
@ -515,7 +515,7 @@
<property name="flat">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8"/>
<layout class="QVBoxLayout" name="userRsidFrameVLayout"/>
</widget>
</item>
<item>
@ -534,7 +534,7 @@
</item>
</layout>
</widget>
<widget class="QWizardPage" name="WebmalPage">
<widget class="QWizardPage" name="WebmailPage">
<property name="title">
<string>RetroShare is better with Friends </string>
</property>
@ -544,9 +544,9 @@
<attribute name="pageId">
<string notr="true">ConnectFriendWizard::Page_WebMail</string>
</attribute>
<layout class="QGridLayout" name="gridLayout">
<layout class="QGridLayout" name="WebmalPageGLayout">
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_10">
<layout class="QHBoxLayout" name="webMailButtonHLayout">
<property name="leftMargin">
<number>9</number>
</property>
@ -560,7 +560,7 @@
<number>9</number>
</property>
<item>
<spacer name="horizontalSpacer_2">
<spacer name="webMailButtonLHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
@ -693,7 +693,7 @@
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<spacer name="webMailButtonRHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
@ -711,37 +711,7 @@
</layout>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="2" column="0">
<spacer name="verticalSpacer_6">
<spacer name="WebmailPageVSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
@ -765,9 +735,9 @@
<attribute name="pageId">
<string notr="true">ConnectFriendWizard::Page_Email</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_9">
<layout class="QVBoxLayout" name="EmailPageVLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<layout class="QHBoxLayout" name="addressHLayout">
<item>
<widget class="QLabel" name="addressLabel">
<property name="text">
@ -785,7 +755,7 @@
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<layout class="QHBoxLayout" name="subjectHLayout">
<item>
<widget class="QLabel" name="subjectLabel">
<property name="text">
@ -817,7 +787,7 @@
<attribute name="pageId">
<string notr="true">ConnectFriendWizard::Page_FriendRequest</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_15">
<layout class="QVBoxLayout" name="FriendRequestPageVLayout">
<property name="leftMargin">
<number>6</number>
</property>
@ -825,10 +795,10 @@
<number>6</number>
</property>
<item>
<widget class="QFrame" name="frame">
<layout class="QVBoxLayout" name="verticalLayout_13">
<widget class="QFrame" name="fr_Frame">
<layout class="QVBoxLayout" name="fr_FrameVLayout">
<item>
<widget class="StyledLabel" name="fr_label_3">
<widget class="StyledLabel" name="fr_InfoTopLabel">
<property name="text">
<string notr="true">You have a friend request from</string>
</property>
@ -857,7 +827,7 @@
<property name="title">
<string>Peer details</string>
</property>
<layout class="QFormLayout" name="formLayout_3">
<layout class="QFormLayout" name="fr_peerDetailsFrameGLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
@ -909,15 +879,15 @@
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="fr_optionslLayout">
<layout class="QHBoxLayout" name="fr_optionsHLayout">
<item>
<widget class="QGroupBox" name="fr_optionsFrame">
<property name="title">
<string>Options</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_14">
<layout class="QVBoxLayout" name="fr_optionsFrameVLayout">
<item>
<layout class="QHBoxLayout" name="fr_groupLayout">
<layout class="QHBoxLayout" name="fr_groupHLayout">
<item>
<widget class="QLabel" name="fr_groupLabel">
<property name="sizePolicy">
@ -961,11 +931,11 @@
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<widget class="QGroupBox" name="fr_RVBox">
<property name="title">
<string>Options</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_12">
<layout class="QVBoxLayout" name="fr_RVBoxVLayout">
<item>
<widget class="QCheckBox" name="_direct_transfer_CB">
<property name="text">
@ -988,7 +958,7 @@
</widget>
</item>
<item>
<spacer name="verticalSpacer_5">
<spacer name="fr_RVBoxVSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
@ -1009,14 +979,14 @@
</widget>
</item>
<item>
<widget class="StyledLabel" name="requestinfolabel_3">
<widget class="StyledLabel" name="fr_InfoBottomLabel">
<property name="text">
<string>To accept the Friend Request, click the Finish button.</string>
</property>
</widget>
</item>
<item>
<spacer name="fr_verticalSpacer">
<spacer name="fr_VSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
@ -1040,7 +1010,7 @@
<attribute name="pageId">
<string notr="true">ConnectFriendWizard::Page_ErrorMessage</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_6">
<layout class="QVBoxLayout" name="ErrorMessagePageVLayout">
<item>
<widget class="QLabel" name="messageLabel">
<property name="text">
@ -1060,7 +1030,7 @@
<attribute name="pageId">
<string notr="true">ConnectFriendWizard::Page_Conclusion</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_17">
<layout class="QVBoxLayout" name="ConclusionPageVLayout">
<item>
<widget class="StyledLabel" name="makefriend_infolabel">
<property name="palette">
@ -1143,7 +1113,7 @@ resources.</string>
</widget>
</item>
<item>
<widget class="StyledLabel" name="fr_label">
<widget class="StyledLabel" name="cp_Label">
<property name="palette">
<palette>
<active>
@ -1230,7 +1200,7 @@ resources.</string>
<property name="title">
<string>Peer details</string>
</property>
<layout class="QFormLayout" name="formLayout">
<layout class="QFormLayout" name="peerDetailsFrameGLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
@ -1342,13 +1312,13 @@ resources.</string>
</widget>
</item>
<item>
<widget class="QFrame" name="horizontalLayout_13">
<layout class="QHBoxLayout" name="horizontalLayout_7">
<widget class="QFrame" name="cp_Frame">
<layout class="QHBoxLayout" name="cp_FrameHLayout">
<property name="spacing">
<number>6</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_18">
<layout class="QVBoxLayout" name="cp_KeyVLayout">
<item>
<widget class="QCheckBox" name="addKeyToKeyring_CB">
<property name="text">
@ -1374,7 +1344,7 @@ resources.</string>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_11">
<layout class="QHBoxLayout" name="cp_AddIPHLayout">
<item>
<widget class="QCheckBox" name="_addIPToWhiteList_CB_2">
<property name="text">
@ -1388,7 +1358,7 @@ resources.</string>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<layout class="QHBoxLayout" name="cp_GroupHLayout">
<item>
<widget class="QLabel" name="groupLabel">
<property name="text">
@ -1404,7 +1374,7 @@ resources.</string>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_19">
<layout class="QVBoxLayout" name="cp_OptionVLayout">
<item>
<widget class="QGroupBox" name="_options_GB">
<property name="title">
@ -1445,7 +1415,7 @@ resources.</string>
</widget>
</item>
<item>
<spacer name="verticalSpacer_4">
<spacer name="cp_OptionVSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
@ -1543,7 +1513,7 @@ resources.</string>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<spacer name="ConclusionPageVSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
@ -1567,9 +1537,9 @@ resources.</string>
<attribute name="pageId">
<string notr="true">ConnectFriendWizard::Page_FriendRecommendations</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_16">
<layout class="QVBoxLayout" name="FriendRecommendationsPageVLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<layout class="QHBoxLayout" name="frec_HLayout">
<item>
<widget class="FriendSelectionWidget" name="frec_recommendList" native="true">
<property name="sizePolicy">

View File

@ -152,6 +152,20 @@ void PGPKeyDialog::load()
ui.pgpfingerprint_label->show();
ui._direct_transfer_CB->setChecked( detail.service_perm_flags & RS_NODE_PERM_DIRECT_DL ) ;
//Add warning to direct source checkbox depends general setting.
switch (rsFiles->filePermDirectDL())
{
case RS_FILE_PERM_DIRECT_DL_YES:
ui._direct_transfer_CB->setIcon(QIcon(":/icons/warning_yellow_128.png"));
ui._direct_transfer_CB->setToolTip(ui._direct_transfer_CB->toolTip().append(tr("\nWarning: In your File-Transfer option, you select allow direct download to Yes.")));
break ;
case RS_FILE_PERM_DIRECT_DL_NO:
ui._direct_transfer_CB->setIcon(QIcon(":/icons/warning_yellow_128.png"));
ui._direct_transfer_CB->setToolTip(ui._direct_transfer_CB->toolTip().append(tr("\nWarning: In your File-Transfer option, you select allow direct download to No.")));
break ;
default: break ;
}
ui._allow_push_CB->setChecked( detail.service_perm_flags & RS_NODE_PERM_ALLOW_PUSH) ;
ui._require_WL_CB->setChecked( detail.service_perm_flags & RS_NODE_PERM_REQUIRE_WL) ;

View File

@ -38,6 +38,7 @@
#include "gui/gxschannels/CreateGxsChannelMsg.h"
#include <iostream>
#include <cmath>
/****
* #define DEBUG_ITEM 1
@ -46,16 +47,29 @@
#define COLOR_NORMAL QColor(248, 248, 248)
#define COLOR_NEW QColor(220, 236, 253)
GxsChannelPostItem::GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate) :
GxsChannelPostItem::GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate,const std::set<RsGxsMessageId>& older_versions) :
GxsFeedItem(feedHolder, feedId, groupId, messageId, isHome, rsGxsChannels, autoUpdate)
{
QVector<RsGxsMessageId> v;
bool self = false;
for(std::set<RsGxsMessageId>::const_iterator it(older_versions.begin());it!=older_versions.end();++it)
v.push_back(*it) ;
if(older_versions.find(messageId) == older_versions.end())
v.push_back(messageId);
setMessageVersions(v) ;
setup();
requestGroup();
requestMessage();
requestComment();
mLoaded = false ;
}
// This code has been suspended because it adds more complexity than usefulness.
// It was used to load a channel post where the post item is already known.
#ifdef SUSPENDED
GxsChannelPostItem::GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsChannelGroup &group, const RsGxsChannelPost &post, bool isHome, bool autoUpdate) :
GxsFeedItem(feedHolder, feedId, post.mMeta.mGroupId, post.mMeta.mMsgId, isHome, rsGxsChannels, autoUpdate)
{
@ -81,10 +95,10 @@ GxsChannelPostItem::GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId,
setup();
//setGroup(group, false);
requestGroup();
setPost(post);
requestComment();
setGroup(group, false);
setPost(post,false);
mLoaded = false ;
}
GxsChannelPostItem::GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsChannelPost &post, bool isHome, bool autoUpdate) :
@ -97,10 +111,30 @@ GxsChannelPostItem::GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId,
setup();
mLoaded = true ;
requestGroup();
setPost(post);
requestComment();
}
#endif
void GxsChannelPostItem::paintEvent(QPaintEvent *e)
{
/* This method employs a trick to trigger a deferred loading. The post and group is requested only
* when actually displayed on the screen. */
if(!mLoaded)
{
mLoaded = true ;
requestGroup();
requestMessage();
requestComment();
}
GxsFeedItem::paintEvent(e) ;
}
GxsChannelPostItem::~GxsChannelPostItem()
{
@ -185,8 +219,9 @@ bool GxsChannelPostItem::setGroup(const RsGxsChannelGroup &group, bool doFill)
mGroup = group;
// if not publisher, hide the edit button. Without the publish key, there's no way to edit a message.
#ifdef DEBUG_ITEM
std::cerr << "Group subscribe flags = " << std::hex << mGroup.mMeta.mSubscribeFlags << std::dec << std::endl;
#endif
if(!IS_GROUP_PUBLISHER(mGroup.mMeta.mSubscribeFlags))
ui->editButton->hide();
@ -348,6 +383,14 @@ void GxsChannelPostItem::fill()
QString title;
if(mPost.mThumbnail.mData != NULL)
{
QPixmap thumbnail;
thumbnail.loadFromData(mPost.mThumbnail.mData, mPost.mThumbnail.mSize, "PNG");
// Wiping data - as its been passed to thumbnail.
ui->logoLabel->setPixmap(thumbnail);
}
if (!mIsHome)
{
if (mCloseOnRead && !IS_MSG_NEW(mPost.mMeta.mMsgStatus)) {
@ -385,9 +428,12 @@ void GxsChannelPostItem::fill()
/* subject */
ui->titleLabel->setText(QString::fromUtf8(mPost.mMeta.mMsgName.c_str()));
uint32_t autorized_lines = (int)floor((ui->logoLabel->height() - ui->titleLabel->height() - ui->buttonHLayout->sizeHint().height())/QFontMetricsF(ui->subjectLabel->font()).height());
// fill first 4 lines of message. (csoler) Disabled the replacement of smileys and links, because the cost is too crazy
//ui->subjectLabel->setText(RsHtml().formatText(NULL, RsStringUtil::CopyLines(QString::fromUtf8(mPost.mMsg.c_str()), 4), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS));
ui->subjectLabel->setText(RsStringUtil::CopyLines(QString::fromUtf8(mPost.mMsg.c_str()), 4)) ;
ui->subjectLabel->setText(RsHtml().formatText(NULL, RsStringUtil::CopyLines(QString::fromUtf8(mPost.mMsg.c_str()), autorized_lines), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS));
//ui->subjectLabel->setText(RsStringUtil::CopyLines(QString::fromUtf8(mPost.mMsg.c_str()), 2)) ;
//QString score = QString::number(post.mTopScore);
// scoreLabel->setText(score);
@ -495,14 +541,6 @@ void GxsChannelPostItem::fill()
layout->addWidget(fi);
}
if(mPost.mThumbnail.mData != NULL)
{
QPixmap thumbnail;
thumbnail.loadFromData(mPost.mThumbnail.mData, mPost.mThumbnail.mSize, "PNG");
// Wiping data - as its been passed to thumbnail.
ui->logoLabel->setPixmap(thumbnail);
}
mInFill = false;
}

View File

@ -41,9 +41,14 @@ class GxsChannelPostItem : public GxsFeedItem
Q_OBJECT
public:
GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate);
GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsChannelGroup &group, const RsGxsChannelPost &post, bool isHome, bool autoUpdate);
GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsChannelPost &post, bool isHome, bool autoUpdate);
// This one is used in NewFeed for incoming channel posts. Only the group and msg ids are known at this point.
// It can be used for all apparences of channel posts. But in rder to merge comments from the previous versions of the post, the list of
// previous posts should be supplied. It's optional. If not supplied only the comments of the new version will be displayed.
GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate, const std::set<RsGxsMessageId>& older_versions = std::set<RsGxsMessageId>());
//GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsChannelGroup &group, const RsGxsChannelPost &post, bool isHome, bool autoUpdate);
//GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsChannelPost &post, bool isHome, bool autoUpdate);
virtual ~GxsChannelPostItem();
bool setGroup(const RsGxsChannelGroup &group, bool doFill = true);
@ -62,6 +67,11 @@ protected:
virtual void doExpand(bool open);
virtual void expandFill(bool first);
// This does nothing except triggering the loading of the post data and comments. This function is mainly used to detect
// when the post is actually made visible.
virtual void paintEvent(QPaintEvent *);
/* GxsGroupFeedItem */
virtual QString groupName();
virtual void loadGroup(const uint32_t &token);
@ -101,6 +111,7 @@ private:
private:
bool mInFill;
bool mCloseOnRead;
bool mLoaded;
RsGxsChannelGroup mGroup;
RsGxsChannelPost mPost;

View File

@ -0,0 +1,284 @@
/*
* Retroshare Gxs Feed Item
*
* Copyright 2014 RetroShare Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "GxsCircleItem.h"
#include "ui_GxsCircleItem.h"
#include "FeedHolder.h"
#include "gui/notifyqt.h"
#include "gui/Circles/CreateCircleDialog.h"
#include "gui/gxs/GxsIdDetails.h"
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <iostream>
/****
* #define DEBUG_ITEM 1
****/
#define COLOR_NORMAL QColor(248, 248, 248)
#define COLOR_NEW QColor(220, 236, 253)
#define CIRCLESDIALOG_GROUPUPDATE 3
GxsCircleItem::GxsCircleItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsCircleId &circleId, const RsGxsId &gxsId, const uint32_t type)
:FeedItem(NULL), mFeedHolder(feedHolder), mFeedId(feedId), mType(type), mCircleId(circleId), mGxsId(gxsId)
{
setup();
}
GxsCircleItem::~GxsCircleItem()
{
delete(ui);
}
void GxsCircleItem::setup()
{
/* Invoke the Qt Designer generated object setup routine */
ui = new Ui::GxsCircleItem;
ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose, true);
/* general ones */
connect(ui->expandButton, SIGNAL(clicked()), this, SLOT(showCircleDetails()));
connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(removeItem()));
/* update gxs information */
RsIdentityDetails idDetails ;
QString idName ;
if(rsIdentity->getIdDetails(mGxsId, idDetails))
idName = tr("for identity ")+QString::fromUtf8(idDetails.mNickname.c_str()) + " (ID=" + QString::fromStdString(mGxsId.toStdString()) + ")" ;
else
idName = tr("for identity ")+QString::fromStdString(mGxsId.toStdString()) ;
/* update circle information */
RsGxsCircleDetails circleDetails;
if (rsGxsCircles->getCircleDetails(mCircleId, circleDetails))
{
if (mType == RS_FEED_ITEM_CIRCLE_MEMB_REQ)
{
ui->titleLabel->setText(tr("You received a membership request for circle:"));
ui->nameLabel->setText(QString::fromUtf8(circleDetails.mCircleName.c_str()));
ui->gxsIdLabel->setText(idName);
ui->acceptButton->setToolTip(tr("Grant membership request"));
ui->revokeButton->setToolTip(tr("Revoke membership request"));
connect(ui->acceptButton, SIGNAL(clicked()), this, SLOT(grantCircleMembership()));
connect(ui->revokeButton, SIGNAL(clicked()), this, SLOT(revokeCircleMembership()));
}
else if (mType == RS_FEED_ITEM_CIRCLE_INVIT_REC)
{
ui->titleLabel->setText(tr("You received an invitation for circle:"));
ui->nameLabel->setText(QString::fromUtf8(circleDetails.mCircleName.c_str()));
ui->gxsIdLabel->setText(idName);
ui->acceptButton->setToolTip(tr("Accept invitation"));
connect(ui->acceptButton, SIGNAL(clicked()), this, SLOT(acceptCircleSubscription()));
ui->revokeButton->setHidden(true);
}
}
else
{
ui->titleLabel->setText(tr("Received event from unknown Circle:"));
ui->nameLabel->setText(QString::fromStdString(mCircleId.toStdString()));
ui->gxsIdLabel->setText(idName);
}
/* Setup TokenQueue */
mCircleQueue = new TokenQueue(rsGxsCircles->getTokenService(), this);
}
bool GxsCircleItem::isSame(const RsGxsCircleId &circleId, const RsGxsId &gxsId, uint32_t type)
{
if ((mCircleId == circleId) && (mGxsId == gxsId) && (mType == type))
{
return true;
}
return false;
}
void GxsCircleItem::removeItem()
{
#ifdef DEBUG_ITEM
std::cerr << "GxsCircleItem::removeItem()" << std::endl;
#endif
if (mFeedHolder)
{
mFeedHolder->lockLayout(this, true);
hide();
mFeedHolder->lockLayout(this, false);
mFeedHolder->deleteFeedItem(this, mFeedId);
}
}
void GxsCircleItem::loadRequest(const TokenQueue * queue, const TokenRequest &req)
{
#ifdef ID_DEBUG
std::cerr << "GxsCircleItem::loadRequest() UserType: " << req.mUserType;
std::cerr << std::endl;
#endif
if(queue == mCircleQueue)
{
#ifdef ID_DEBUG
std::cerr << "CirclesDialog::loadRequest() UserType: " << req.mUserType;
std::cerr << std::endl;
#endif
/* now switch on req */
switch(req.mUserType)
{
case CIRCLESDIALOG_GROUPUPDATE:
updateCircleGroup(req.mToken);
break;
default:
std::cerr << "GxsCircleItem::loadRequest() ERROR: INVALID TYPE";
std::cerr << std::endl;
break;
}
}
}
/*********** SPECIFIC FUNCTIONS ***********************/
void GxsCircleItem::showCircleDetails()
{
CreateCircleDialog dlg;
dlg.editExistingId(RsGxsGroupId(mCircleId), true, mType != RS_FEED_ITEM_CIRCLE_MEMB_REQ) ;
dlg.exec();
}
void GxsCircleItem::acceptCircleSubscription()
{
if (rsGxsCircles->requestCircleMembership(mGxsId, mCircleId))
removeItem();
}
void GxsCircleItem::grantCircleMembership()
{
RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
std::list<RsGxsGroupId> grps ;
grps.push_back(RsGxsGroupId(mCircleId));
uint32_t token;
mCircleQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, grps, CIRCLESDIALOG_GROUPUPDATE);
CircleUpdateOrder c ;
c.token = token ;
c.gxs_id = mGxsId ;
c.action = CircleUpdateOrder::GRANT_MEMBERSHIP ;
mCircleUpdates[token] = c ;
}
void GxsCircleItem::revokeCircleMembership()
{
RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
std::list<RsGxsGroupId> grps;
grps.push_back(RsGxsGroupId(mCircleId));
uint32_t token;
mCircleQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, grps, CIRCLESDIALOG_GROUPUPDATE);
CircleUpdateOrder c;
c.token = token;
c.gxs_id = mGxsId;
c.action = CircleUpdateOrder::REVOKE_MEMBERSHIP;
mCircleUpdates[token] = c;
}
void GxsCircleItem::updateCircleGroup(const uint32_t& token)
{
#ifdef ID_DEBUG
std::cerr << "Loading circle info" << std::endl;
#endif
std::vector<RsGxsCircleGroup> circle_grp_v ;
rsGxsCircles->getGroupData(token, circle_grp_v);
if (circle_grp_v.empty())
{
std::cerr << "(EE) unexpected empty result from getGroupData. Cannot process circle now!" << std::endl;
return ;
}
if (circle_grp_v.size() != 1)
{
std::cerr << "(EE) very weird result from getGroupData. Should get exactly one circle" << std::endl;
return ;
}
RsGxsCircleGroup cg = circle_grp_v.front();
/* now mark all the members */
//std::set<RsGxsId> members = cg.mInvitedMembers;
std::map<uint32_t,CircleUpdateOrder>::iterator it = mCircleUpdates.find(token) ;
if(it == mCircleUpdates.end())
{
std::cerr << "(EE) Cannot find token " << token << " to perform group update!" << std::endl;
return ;
}
if(it->second.action == CircleUpdateOrder::GRANT_MEMBERSHIP)
cg.mInvitedMembers.insert(it->second.gxs_id) ;
else if(it->second.action == CircleUpdateOrder::REVOKE_MEMBERSHIP)
cg.mInvitedMembers.erase(it->second.gxs_id) ;
else
{
std::cerr << "(EE) unrecognised membership action to perform: " << it->second.action << "!" << std::endl;
return ;
}
uint32_t token2 ;
rsGxsCircles->updateGroup(token2,cg) ;
mCircleUpdates.erase(it) ;
}

View File

@ -0,0 +1,98 @@
/*
* Retroshare Gxs Feed Item
*
* Copyright 2014 RetroShare Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#ifndef _GXSCIRCLEITEM_H
#define _GXSCIRCLEITEM_H
#include <retroshare/rsgxscircles.h>
#include "FeedItem.h"
#include "util/TokenQueue.h"
namespace Ui {
class GxsCircleItem;
}
class FeedHolder;
struct CircleUpdateOrder
{
enum { UNKNOWN_ACTION=0x00, GRANT_MEMBERSHIP=0x01, REVOKE_MEMBERSHIP=0x02 };
uint32_t token ;
RsGxsId gxs_id ;
uint32_t action ;
};
class GxsCircleItem : public FeedItem, public TokenResponse
{
Q_OBJECT
public:
/** Default Constructor */
GxsCircleItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsCircleId &circleId, const RsGxsId &gxsId, const uint32_t type);
virtual ~GxsCircleItem();
bool isSame(const RsGxsCircleId &circleId, const RsGxsId &gxsId, uint32_t type);
void loadRequest(const TokenQueue *queue, const TokenRequest &req);
protected:
/* FeedItem */
virtual void doExpand(bool /*open*/) {}
void updateCircleGroup(const uint32_t& token);
private slots:
/* default stuff */
void removeItem();
void showCircleDetails();
void acceptCircleSubscription();
void grantCircleMembership() ;
void revokeCircleMembership();
private:
void setup();
FeedHolder *mFeedHolder;
uint32_t mFeedId;
uint32_t mType;
RsGxsCircleId mCircleId;
RsGxsId mGxsId;
TokenQueue *mCircleQueue;
std::map<uint32_t, CircleUpdateOrder> mCircleUpdates ;
/** Qt Designer generated object */
Ui::GxsCircleItem *ui;
};
#endif

View File

@ -0,0 +1,298 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GxsCircleItem</class>
<widget class="QWidget" name="GxsCircleItem">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>618</width>
<height>96</height>
</rect>
</property>
<layout class="QGridLayout" name="GxsCircleItemGLayout">
<property name="leftMargin">
<number>1</number>
</property>
<property name="topMargin">
<number>1</number>
</property>
<property name="rightMargin">
<number>1</number>
</property>
<property name="bottomMargin">
<number>1</number>
</property>
<item row="0" column="0">
<widget class="QFrame" name="frame">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>215</red>
<green>215</green>
<blue>215</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>215</red>
<green>215</green>
<blue>215</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>215</red>
<green>215</green>
<blue>215</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>215</red>
<green>215</green>
<blue>215</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>215</red>
<green>215</green>
<blue>215</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>215</red>
<green>215</green>
<blue>215</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<layout class="QGridLayout" name="frameGLayout">
<item row="0" column="0">
<layout class="QGridLayout" name="topGLayout">
<item row="0" column="0" rowspan="2">
<widget class="QLabel" name="logoLabel">
<property name="minimumSize">
<size>
<width>70</width>
<height>70</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>70</width>
<height>70</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../icons.qrc">:/icons/svg/circles.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="nameHLayout">
<item>
<widget class="QLabel" name="titleLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<italic>true</italic>
<bold>true</bold>
</font>
</property>
<property name="text">
<string notr="true">Circle</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="nameLabel">
<property name="text">
<string notr="true">name</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="nameHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="toolbarHLayout">
<item>
<widget class="QLabel" name="gxsIdLabel">
<property name="text">
<string notr="true">name</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="tollbarHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>254</width>
<height>28</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="acceptButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<normaloff>:/images/accepted16.png</normaloff>:/images/accepted16.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="revokeButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<normaloff>:/images/cancel.png</normaloff>:/images/cancel.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="expandButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="toolTip">
<string>Details</string>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<normaloff>:/images/edit_add24.png</normaloff>:/images/edit_add24.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="clearButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="toolTip">
<string>Remove Item</string>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<normaloff>:/images/close_normal.png</normaloff>:/images/close_normal.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../images.qrc"/>
<include location="../icons.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>1237</width>
<height>622</height>
<height>1145</height>
</rect>
</property>
<property name="windowTitle">
@ -370,7 +370,7 @@
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Messages will only be distributed to the selected subset of your friend nodes. They will not forward messages with each other, but only use your own node as a central hub to distribute them.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Only For Your Friends</string>
<string>Restricted node group </string>
</property>
<property name="icon">
<iconset resource="../icons.qrc">
@ -917,8 +917,8 @@
</customwidget>
</customwidgets>
<resources>
<include location="../images.qrc"/>
<include location="../icons.qrc"/>
<include location="../images.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -815,8 +815,8 @@ void GxsGroupFrameDialog::insertGroupsData(const std::list<RsGroupMetaData> &gro
}
else
{
/* rate the others by popularity */
popMap.insert(std::make_pair(it->mPop, groupItemInfo));
//popMap.insert(std::make_pair(it->mPop, groupItemInfo)); /* rate the others by popularity */
popMap.insert(std::make_pair(it->mLastPost, groupItemInfo)); /* rate the others by time of last post */
}
}
@ -830,17 +830,17 @@ void GxsGroupFrameDialog::insertGroupsData(const std::list<RsGroupMetaData> &gro
uint32_t i = 0;
uint32_t popLimit = 0;
std::multimap<uint32_t, GroupItemInfo>::reverse_iterator rit;
for(rit = popMap.rbegin(); ((rit != popMap.rend()) && (i < popCount)); ++rit, ++i) ;
if (rit != popMap.rend()) {
popLimit = rit->first;
}
//for(rit = popMap.rbegin(); ((rit != popMap.rend()) && (i < popCount)); ++rit, ++i) ;
//if (rit != popMap.rend()) {
// popLimit = rit->first;
//}
for (rit = popMap.rbegin(); rit != popMap.rend(); ++rit) {
if (rit->second.popularity < (int) popLimit) {
otherList.append(rit->second);
} else {
for (rit = popMap.rbegin(); rit != popMap.rend(); ++rit,++i) {
//if (rit->second.popularity > (int) popLimit) {
if(i < popCount)
popList.append(rit->second);
}
else
otherList.append(rit->second);
}
/* now we can add them in as a tree! */

View File

@ -407,10 +407,12 @@ void GxsChannelPostsWidget::createPostItem(const RsGxsChannelPost &post, bool re
if(item)
{
ui->feedWidget->removeFeedItem(item) ;
RsGxsChannelGroup dummyGroup;
dummyGroup.mMeta.mGroupId = groupId();
dummyGroup.mMeta.mSubscribeFlags = 0xffffffff;
GxsChannelPostItem *item = new GxsChannelPostItem(this, 0, dummyGroup, post, true, false);
//RsGxsChannelGroup dummyGroup;
//dummyGroup.mMeta.mGroupId = groupId();
//dummyGroup.mMeta.mSubscribeFlags = 0xffffffff;
//GxsChannelPostItem *item = new GxsChannelPostItem(this, 0, dummyGroup, post, true, false);
GxsChannelPostItem *item = new GxsChannelPostItem(this, 0, post.mMeta.mGroupId, post.mMeta.mMsgId, true, false,post.mOlderVersions);
ui->feedWidget->addFeedItem(item, ROLE_PUBLISH, QDateTime::fromTime_t(post.mMeta.mPublishTs));
return ;
@ -427,10 +429,13 @@ void GxsChannelPostsWidget::createPostItem(const RsGxsChannelPost &post, bool re
ui->feedWidget->setSort(item, ROLE_PUBLISH, QDateTime::fromTime_t(post.mMeta.mPublishTs));
} else {
/* Group is not always available because of the TokenQueue */
RsGxsChannelGroup dummyGroup;
dummyGroup.mMeta.mGroupId = groupId();
dummyGroup.mMeta.mSubscribeFlags = 0xffffffff;
GxsChannelPostItem *item = new GxsChannelPostItem(this, 0, dummyGroup, post, true, false);
//RsGxsChannelGroup dummyGroup;
//dummyGroup.mMeta.mGroupId = groupId();
//dummyGroup.mMeta.mSubscribeFlags = 0xffffffff;
//GxsChannelPostItem *item = new GxsChannelPostItem(this, 0, dummyGroup, post, true, false);
GxsChannelPostItem *item = new GxsChannelPostItem(this, 0, post.mMeta.mGroupId, post.mMeta.mMsgId, true, false,post.mOlderVersions);
ui->feedWidget->addFeedItem(item, ROLE_PUBLISH, QDateTime::fromTime_t(post.mMeta.mPublishTs));
}

View File

@ -135,7 +135,7 @@ MessageWidget::MessageWidget(bool controlled, QWidget *parent, Qt::WindowFlags f
connect(ui.expandFilesButton, SIGNAL(clicked()), this, SLOT(togglefileview()));
connect(ui.downloadButton, SIGNAL(clicked()), this, SLOT(getallrecommended()));
connect(ui.msgText, SIGNAL(anchorClicked(QUrl)), this, SLOT(anchorClicked(QUrl)));
connect(ui.sendinviteButton, SIGNAL(clicked()), this, SLOT(sendInvite()));
connect(ui.sendInviteButton, SIGNAL(clicked()), this, SLOT(sendInvite()));
connect(NotifyQt::getInstance(), SIGNAL(messagesTagsChanged()), this, SLOT(messagesTagsChanged()));
connect(NotifyQt::getInstance(), SIGNAL(messagesChanged()), this, SLOT(messagesChanged()));
@ -160,10 +160,13 @@ MessageWidget::MessageWidget(bool controlled, QWidget *parent, Qt::WindowFlags f
QFont font = QFont("Arial", 10, QFont::Bold);
ui.subjectText->setFont(font);
ui.bcclabel->setVisible(false);
ui.bccText->setVisible(false);
ui.cclabel->setVisible(false);
ui.toText->setMaximumHeight(ui.toText->fontMetrics().lineSpacing()*1.5);
ui.ccLabel->setVisible(false);
ui.ccText->setVisible(false);
ui.ccText->setMaximumHeight(ui.ccText->fontMetrics().lineSpacing()*1.5);
ui.bccLabel->setVisible(false);
ui.bccText->setVisible(false);
ui.bccText->setMaximumHeight(ui.bccText->fontMetrics().lineSpacing()*1.5);
ui.tagsLabel->setVisible(false);
@ -454,11 +457,11 @@ void MessageWidget::fill(const std::string &msgId)
ui.fromText->setText("");
ui.filesText->setText("");
ui.cclabel->setVisible(false);
ui.ccLabel->setVisible(false);
ui.ccText->setVisible(false);
ui.ccText->clear();
ui.bcclabel->setVisible(false);
ui.bccLabel->setVisible(false);
ui.bccText->setVisible(false);
ui.bccText->clear();
@ -519,7 +522,7 @@ void MessageWidget::fill(const std::string &msgId)
if (!msgInfo.rspeerid_msgcc.empty() || !msgInfo.rsgxsid_msgcc.empty())
{
ui.cclabel->setVisible(true);
ui.ccLabel->setVisible(true);
ui.ccText->setVisible(true);
text.clear();
@ -528,14 +531,14 @@ void MessageWidget::fill(const std::string &msgId)
ui.ccText->setText(text);
} else {
ui.cclabel->setVisible(false);
ui.ccLabel->setVisible(false);
ui.ccText->setVisible(false);
ui.ccText->clear();
}
if (!msgInfo.rspeerid_msgbcc.empty() || !msgInfo.rsgxsid_msgbcc.empty())
{
ui.bcclabel->setVisible(true);
ui.bccLabel->setVisible(true);
ui.bccText->setVisible(true);
text.clear();
@ -544,7 +547,7 @@ void MessageWidget::fill(const std::string &msgId)
ui.bccText->setText(text);
} else {
ui.bcclabel->setVisible(false);
ui.bccLabel->setVisible(false);
ui.bccText->setVisible(false);
ui.bccText->clear();
}

View File

@ -10,7 +10,7 @@
<height>539</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<layout class="QHBoxLayout" name="MessageWidgetHLayout">
<property name="leftMargin">
<number>0</number>
</property>
@ -23,246 +23,251 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QSplitter" name="msgSplitter">
<item>
<widget class="QSplitter" name="mainSplitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QSplitter" name="msgSplitter_2">
<widget class="QSplitter" name="msgSplitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QVBoxLayout" name="msgSplitterVLayout">
<property name="spacing">
<number>2</number>
</property>
<item>
<layout class="QHBoxLayout" name="_4">
<layout class="QGridLayout" name="msgSplitterGLayout">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>0</number>
<property name="horizontalSpacing">
<number>6</number>
</property>
<item>
<layout class="QGridLayout" name="_5">
<property name="horizontalSpacing">
<number>6</number>
<property name="verticalSpacing">
<number>3</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="subjectLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="verticalSpacing">
<number>3</number>
<property name="text">
<string>Subject:</string>
</property>
<item row="0" column="0">
<widget class="QLabel" name="subjectlabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Subject:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="fromlabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>From:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="2" colspan="2">
<widget class="QLabel" name="fromText">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="2" colspan="2">
<layout class="QHBoxLayout" name="subjectHLayout">
<item>
<widget class="QLabel" name="subjectText">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="tolabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>To:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="2" colspan="2">
<widget class="QLabel" name="toText">
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="cclabel">
<item>
<widget class="QLabel" name="dateText">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>Cc:</string>
<string notr="true">Date</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="wordWrap">
<bool>false</bool>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="bcclabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Bcc:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="2" colspan="2">
<widget class="QLabel" name="ccText">
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="2" colspan="2">
<widget class="QLabel" name="bccText">
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="tagsLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Tags:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="2" colspan="2">
<layout class="QHBoxLayout" name="tagLayout"/>
</item>
<item row="0" column="2" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="subjectText">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="dateText">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string notr="true">Date</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="fromLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>From:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="2" colspan="2">
<widget class="QLabel" name="fromText">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="toLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>To:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="2" colspan="2">
<widget class="RSTextBrowser" name="toText">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16</height>
</size>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="ccLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Cc:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="2" colspan="2">
<widget class="RSTextBrowser" name="ccText">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16</height>
</size>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="bccLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Bcc:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="4" column="2" colspan="2">
<widget class="RSTextBrowser" name="bccText">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16</height>
</size>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="tagsLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Tags:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="2" colspan="2">
<layout class="QHBoxLayout" name="tagLayout"/>
</item>
</layout>
</item>
<item>
@ -403,14 +408,14 @@
</widget>
</item>
<item>
<widget class="QPushButton" name="sendinviteButton">
<widget class="QPushButton" name="sendInviteButton">
<property name="text">
<string>Send Invite</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<spacer name="inviteHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
@ -426,9 +431,9 @@
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="_2">
<layout class="QHBoxLayout" name="filesHLayout">
<item>
<layout class="QGridLayout" name="_3">
<layout class="QGridLayout" name="filesGLayout">
<property name="leftMargin">
<number>0</number>
</property>
@ -445,7 +450,7 @@
<number>6</number>
</property>
<item row="0" column="2">
<widget class="QLabel" name="label_6">
<widget class="QLabel" name="attLabel">
<property name="text">
<string/>
</property>
@ -455,7 +460,7 @@
</widget>
</item>
<item row="0" column="4">
<widget class="QLabel" name="label_2">
<widget class="QLabel" name="recFilesLabel">
<property name="text">
<string>Recommended Files</string>
</property>
@ -498,7 +503,7 @@
</layout>
</item>
<item>
<spacer>
<spacer name="filesHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>

View File

@ -22,6 +22,7 @@
#include "ChannelPage.h"
#include "rsharesettings.h"
#include "util/misc.h"
#include "gui/notifyqt.h"
ChannelPage::ChannelPage(QWidget * parent, Qt::WindowFlags flags)
: ConfigPage(parent, flags)
@ -33,10 +34,14 @@ ChannelPage::ChannelPage(QWidget * parent, Qt::WindowFlags flags)
ui.groupFrameSettingsWidget->setOpenAllInNewTabText(tr("Open each channel in a new tab"));
ui.groupFrameSettingsWidget->setType(GroupFrameSettings::Channel) ;
connect(ui.loadThreadCheckBox,SIGNAL(toggled(bool)),this,SLOT(updateLoadThread)) ;
connect(ui.loadThreadCheckBox,SIGNAL(toggled(bool)),this,SLOT(updateLoadThread())) ;
}
void ChannelPage::updateLoadThread() { Settings->setChannelLoadThread(ui.loadThreadCheckBox->isChecked()); }
void ChannelPage::updateLoadThread()
{
Settings->setChannelLoadThread(ui.loadThreadCheckBox->isChecked());
NotifyQt::getInstance()->notifySettingsChanged();
}
ChannelPage::~ChannelPage()
{

View File

@ -162,6 +162,7 @@ NotifyPage::NotifyPage(QWidget * parent, Qt::WindowFlags flags)
connect(ui.message_ConnectAttempt, SIGNAL(toggled(bool)), this, SLOT(updateMessageFlags())) ;
connect(ui.notify_Peers, SIGNAL(toggled(bool)), this, SLOT(updateNewsFeedFlags()));
connect(ui.notify_Circles, SIGNAL(toggled(bool)), this, SLOT(updateNewsFeedFlags()));
connect(ui.notify_Channels, SIGNAL(toggled(bool)), this, SLOT(updateNewsFeedFlags()));
connect(ui.notify_Forums, SIGNAL(toggled(bool)), this, SLOT(updateNewsFeedFlags()));
connect(ui.notify_Posted, SIGNAL(toggled(bool)), this, SLOT(updateNewsFeedFlags()));
@ -195,6 +196,8 @@ uint NotifyPage::getNewsFlags()
if (ui.notify_Peers->isChecked())
newsFlags |= RS_FEED_TYPE_PEER;
if (ui.notify_Circles->isChecked())
newsFlags |= RS_FEED_TYPE_CIRCLE;
if (ui.notify_Channels->isChecked())
newsFlags |= RS_FEED_TYPE_CHANNEL;
if (ui.notify_Forums->isChecked())
@ -324,6 +327,7 @@ void NotifyPage::load()
whileBlocking(ui.popup_ConnectAttempt)->setChecked(notifyflags & RS_POPUP_CONNECT_ATTEMPT);
whileBlocking(ui.notify_Peers)->setChecked(newsflags & RS_FEED_TYPE_PEER);
whileBlocking(ui.notify_Circles)->setChecked(newsflags & RS_FEED_TYPE_CIRCLE);
whileBlocking(ui.notify_Channels)->setChecked(newsflags & RS_FEED_TYPE_CHANNEL);
whileBlocking(ui.notify_Forums)->setChecked(newsflags & RS_FEED_TYPE_FORUM);
whileBlocking(ui.notify_Posted)->setChecked(newsflags & RS_FEED_TYPE_POSTED);

View File

@ -51,6 +51,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="notify_Circles">
<property name="text">
<string>Circles</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="notify_Channels">
<property name="text">

View File

@ -1,281 +0,0 @@
/****************************************************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 2006 - 2010 RetroShare Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
****************************************************************/
#include "RelayPage.h"
#include "rshare.h"
#include <iostream>
#include <retroshare/rsiface.h>
#include <retroshare/rsfiles.h>
#include <retroshare/rspeers.h>
#include <retroshare/rsdht.h>
#include "util/misc.h"
#include <QTimer>
RelayPage::RelayPage(QWidget * parent, Qt::WindowFlags flags)
: ConfigPage(parent, flags)
{
/* Invoke the Qt Designer generated object setup routine */
ui.setupUi(this);
QObject::connect(ui.noFriendSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateRelayOptions()));
QObject::connect(ui.noFOFSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateRelayOptions()));
QObject::connect(ui.noGeneralSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateRelayOptions()));
QObject::connect(ui.bandFriendSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateRelayOptions()));
QObject::connect(ui.bandFOFSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateRelayOptions()));
QObject::connect(ui.bandGeneralSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateRelayOptions()));
QObject::connect(ui.addPushButton,SIGNAL(clicked()),this,SLOT(addServer()));
QObject::connect(ui.removePushButton,SIGNAL(clicked()),this,SLOT(removeServer()));
QObject::connect(ui.DhtLineEdit,SIGNAL(textChanged(const QString &)),this,SLOT(checkKey()));
QObject::connect(ui.enableCheckBox,SIGNAL(stateChanged(int)),this,SLOT(updateEnabled()));
QObject::connect(ui.serverCheckBox,SIGNAL(stateChanged(int)),this,SLOT(updateEnabled()));
QObject::connect(ui.noFriendSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateTotals()));
QObject::connect(ui.bandFriendSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateTotals()));
QObject::connect(ui.noFOFSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateTotals()));
QObject::connect(ui.bandFOFSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateTotals()));
QObject::connect(ui.noGeneralSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateTotals()));
QObject::connect(ui.bandGeneralSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateTotals()));
QObject::connect(ui.enableCheckBox,SIGNAL(toggled(bool)),this,SLOT(updateRelayMode()));
QObject::connect(ui.serverCheckBox,SIGNAL(toggled(bool)),this,SLOT(updateRelayMode()));
}
QString RelayPage::helpText() const
{
return tr("<h1><img width=\"24\" src=\":/icons/help_64.png\">&nbsp;&nbsp;Relays</h1> \
<p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare \
users who cannot connect directly, e.g. because they're firewalled.</p> \
<p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply \
benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former,\
you may specify the bandwidth allocated when acting as a relay for friends of you, for friends \
of your friends, or anyone in the Retroshare network.</p> \
<p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it \
is encrypted and authenticated by the two relayed nodes.</p>") ;
}
void RelayPage::updateTotals()
{
int nFriends = ui.noFriendSpinBox->value();
int friendBandwidth = ui.bandFriendSpinBox->value();
int nFOF = ui.noFOFSpinBox->value();
int fofBandwidth = ui.bandFOFSpinBox->value();
int nGeneral = ui.noGeneralSpinBox->value();
int genBandwidth = ui.bandGeneralSpinBox->value();
int total = nFriends + nFOF + nGeneral;
rsDht->setRelayAllowance(RSDHT_RELAY_CLASS_ALL, total, 0);
rsDht->setRelayAllowance(RSDHT_RELAY_CLASS_FRIENDS, nFriends, 1024 * friendBandwidth);
rsDht->setRelayAllowance(RSDHT_RELAY_CLASS_FOF, nFOF, 1024 * fofBandwidth);
rsDht->setRelayAllowance(RSDHT_RELAY_CLASS_GENERAL, nGeneral, 1024 * genBandwidth);
}
/** Saves the changes on this page */
void RelayPage::updateRelayMode()
{
uint32_t relayMode = 0;
if (ui.enableCheckBox->isChecked())
{
relayMode |= RSDHT_RELAY_ENABLED;
if (ui.serverCheckBox->isChecked())
{
relayMode |= RSDHT_RELAY_MODE_ON;
}
else
{
relayMode |= RSDHT_RELAY_MODE_OFF;
}
}
else
{
relayMode |= RSDHT_RELAY_MODE_OFF;
}
rsDht->setRelayMode(relayMode);
}
/** Loads the settings for this page */
void RelayPage::load()
{
uint32_t count;
uint32_t bandwidth;
rsDht->getRelayAllowance(RSDHT_RELAY_CLASS_FRIENDS, count, bandwidth);
whileBlocking(ui.noFriendSpinBox)->setValue(count);
whileBlocking(ui.bandFriendSpinBox)->setValue(bandwidth / 1024);
rsDht->getRelayAllowance(RSDHT_RELAY_CLASS_FOF, count, bandwidth);
whileBlocking(ui.noFOFSpinBox)->setValue(count);
whileBlocking(ui.bandFOFSpinBox)->setValue(bandwidth / 1024);
rsDht->getRelayAllowance(RSDHT_RELAY_CLASS_GENERAL, count, bandwidth);
whileBlocking(ui.noGeneralSpinBox)->setValue(count);
whileBlocking(ui.bandGeneralSpinBox)->setValue(bandwidth / 1024);
updateTotals();
uint32_t relayMode = rsDht->getRelayMode();
if (relayMode & RSDHT_RELAY_ENABLED)
{
whileBlocking(ui.enableCheckBox)->setCheckState(Qt::Checked);
if ((relayMode & RSDHT_RELAY_MODE_MASK) == RSDHT_RELAY_MODE_OFF)
{
whileBlocking(ui.serverCheckBox)->setCheckState(Qt::Unchecked);
}
else
{
whileBlocking(ui.serverCheckBox)->setCheckState(Qt::Checked);
}
}
else
{
whileBlocking(ui.enableCheckBox)->setCheckState(Qt::Unchecked);
whileBlocking(ui.serverCheckBox)->setCheckState(Qt::Unchecked);
}
loadServers();
updateRelayOptions();
updateEnabled();
checkKey();
}
void RelayPage::loadServers()
{
std::list<std::string> servers;
std::list<std::string>::iterator it;
rsDht->getRelayServerList(servers);
ui.serverTreeWidget->clear();
for(it = servers.begin(); it != servers.end(); ++it)
{
QTreeWidgetItem *item = new QTreeWidgetItem();
item->setData(0, Qt::DisplayRole, QString::fromStdString(*it));
ui.serverTreeWidget->addTopLevelItem(item);
}
}
void RelayPage::updateRelayOptions()
{
int nFriends = ui.noFriendSpinBox->value();
int friendBandwidth = ui.bandFriendSpinBox->value();
int nFOF = ui.noFOFSpinBox->value();
int fofBandwidth = ui.bandFOFSpinBox->value();
int nGeneral = ui.noGeneralSpinBox->value();
int genBandwidth = ui.bandGeneralSpinBox->value();
ui.totalFriendLineEdit->setText(QString::number(nFriends * friendBandwidth * 2));
ui.totalFOFLineEdit->setText(QString::number(nFOF * fofBandwidth * 2));
ui.totalGeneralLineEdit->setText(QString::number(nGeneral * genBandwidth * 2));
ui.totalBandwidthLineEdit->setText(QString::number((nFriends * friendBandwidth + nFOF * fofBandwidth + nGeneral * genBandwidth) * 2));
ui.noTotalLineEdit->setText(QString::number(nFriends + nFOF + nGeneral));
}
void RelayPage::updateEnabled()
{
std::cerr << "RelayPage::updateEnabled()" << std::endl;
if (ui.enableCheckBox->isChecked())
{
ui.relayOptionGBox->setEnabled(true);
if (ui.serverCheckBox->isChecked())
{
std::cerr << "RelayPage::updateEnabled() Both Enabled" << std::endl;
ui.serverGroupBox->setEnabled(true);
}
else
{
std::cerr << "RelayPage::updateEnabled() Options Only Enabled" << std::endl;
ui.serverGroupBox->setEnabled(false);
}
}
else
{
std::cerr << "RelayPage::updateEnabled() Both Disabled" << std::endl;
ui.relayOptionGBox->setEnabled(false);
ui.serverGroupBox->setEnabled(false);
}
}
void RelayPage::checkKey()
{
std::string server = ui.DhtLineEdit->text().toStdString();
std::cerr << "RelayPage::checkKey() length: " << server.length();
std::cerr << std::endl;
if (server.length() == 40)
{
ui.keyOkBox->setChecked(Qt::Checked);
}
else
{
ui.keyOkBox->setChecked(Qt::Unchecked);
}
}
void RelayPage::addServer()
{
std::cerr << "RelayPage::addServer()";
std::cerr << std::endl;
if (!ui.keyOkBox->isChecked())
{
return;
}
std::string server = ui.DhtLineEdit->text().toStdString();
bool ok = rsDht->addRelayServer(server);
if (ok)
{
ui.DhtLineEdit->setText(QString(""));
}
loadServers();
}
void RelayPage::removeServer()
{
QTreeWidgetItem *item = ui.serverTreeWidget->currentItem();
if (item)
{
std::string server = item->data(0, Qt::DisplayRole).toString().toStdString();
rsDht->removeRelayServer(server);
}
loadServers();
}

View File

@ -1,61 +0,0 @@
/****************************************************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 2006 - 2010 RetroShare Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
****************************************************************/
#ifndef RELAYPAGE_H
#define RELAYPAGE_H
# include <QWidget>
#include <retroshare-gui/configpage.h>
#include "ui_RelayPage.h"
class RelayPage: public ConfigPage
{
Q_OBJECT
public:
RelayPage(QWidget * parent = 0, Qt::WindowFlags flags = 0);
~RelayPage() {}
/** Loads the settings for this page */
virtual void load();
virtual QPixmap iconPixmap() const { return QPixmap(":/icons/settings/server.svg") ; }
virtual QString pageName() const { return tr("Relay") ; }
virtual QString helpText() const ;
public slots:
void updateRelayOptions();
void updateEnabled();
void checkKey();
void addServer();
void removeServer();
void loadServers();
void updateTotals();
void updateRelayMode();
private:
Ui::RelayPage ui;
};
#endif //RELAYPAGE_H

View File

@ -1,416 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>RelayPage</class>
<widget class="QWidget" name="RelayPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>794</width>
<height>546</height>
</rect>
</property>
<layout class="QVBoxLayout" name="RelayPageVLayout">
<item>
<layout class="QHBoxLayout" name="topHLayout">
<item>
<widget class="QCheckBox" name="enableCheckBox">
<property name="text">
<string>Enable Relay Connections</string>
</property>
</widget>
</item>
<item>
<spacer name="topLeftHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="serverCheckBox">
<property name="text">
<string>Use Relay Servers</string>
</property>
</widget>
</item>
<item>
<spacer name="topRightHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="relayOptionGBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="title">
<string>Relay options</string>
</property>
<layout class="QGridLayout" name="relayOptionGBoxGLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<spacer name="optionHeaderLHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>110</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<widget class="QLabel" name="headerNumberLabel">
<property name="text">
<string>Number</string>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="optionHeaderRHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>6</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="3">
<widget class="QLabel" name="headerBandwidthLabel">
<property name="text">
<string>Bandwidth per link</string>
</property>
</widget>
</item>
<item row="0" column="4" rowspan="7">
<widget class="Line" name="totalVLine">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QLabel" name="headerTotalLabel">
<property name="text">
<string>Total Bandwidth</string>
</property>
</widget>
</item>
<item row="1" column="0" rowspan="2">
<widget class="QLabel" name="friendLabel">
<property name="text">
<string>Friends</string>
</property>
</widget>
</item>
<item row="1" column="1" rowspan="2">
<widget class="QSpinBox" name="noFriendSpinBox">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>99</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="1" column="2" rowspan="2">
<widget class="QLabel" name="xFriendLabel">
<property name="text">
<string notr="true">x</string>
</property>
</widget>
</item>
<item row="1" column="3" rowspan="2">
<widget class="QSpinBox" name="bandFriendSpinBox">
<property name="suffix">
<string>kB/s</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
<item row="2" column="5">
<widget class="QLineEdit" name="totalFriendLineEdit">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0" rowspan="2">
<widget class="QLabel" name="fofLabel">
<property name="text">
<string>Friends of Friends</string>
</property>
</widget>
</item>
<item row="3" column="1" rowspan="2">
<widget class="QSpinBox" name="noFOFSpinBox">
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
<item row="3" column="2" rowspan="2">
<widget class="QLabel" name="xFOFLabel">
<property name="text">
<string notr="true">x</string>
</property>
</widget>
</item>
<item row="3" column="3" rowspan="2">
<widget class="QSpinBox" name="bandFOFSpinBox">
<property name="suffix">
<string>kB/s</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
<item row="4" column="5">
<widget class="QLineEdit" name="totalFOFLineEdit">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="0" rowspan="2">
<widget class="QLabel" name="generalLabel">
<property name="text">
<string>General</string>
</property>
</widget>
</item>
<item row="5" column="1" rowspan="2">
<widget class="QSpinBox" name="noGeneralSpinBox">
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
<item row="5" column="2" rowspan="2">
<widget class="QLabel" name="xGeneralLabel">
<property name="text">
<string notr="true">x</string>
</property>
</widget>
</item>
<item row="5" column="3" rowspan="2">
<widget class="QSpinBox" name="bandGeneralSpinBox">
<property name="suffix">
<string>kB/s</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
<item row="6" column="5">
<widget class="QLineEdit" name="totalGeneralLineEdit">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="7" column="0" colspan="6">
<widget class="Line" name="totalHLine">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="totalLabel">
<property name="text">
<string>Total:</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLineEdit" name="noTotalLineEdit">
<property name="focusPolicy">
<enum>Qt::WheelFocus</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="8" column="2" colspan="2">
<spacer name="totalHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>123</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="8" column="5">
<widget class="QLineEdit" name="totalBandwidthLineEdit">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="9" column="0" colspan="6">
<widget class="QLabel" name="warningLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true"> border: 1px solid #DCDC41;
border-radius: 6px;
background: #FFFFD7;
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2);
</string>
</property>
<property name="text">
<string>Warning: This bandwidth adds up to the max bandwidth.</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="serverGroupBox">
<property name="title">
<string>Relay Server Setup</string>
</property>
<layout class="QGridLayout" name="serverGroupBoxGLayout">
<item row="0" column="0">
<widget class="QLineEdit" name="DhtLineEdit">
<property name="inputMask">
<string notr="true">HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="keyOkBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string/>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="addPushButton">
<property name="text">
<string>Add Server</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QTreeWidget" name="serverTreeWidget">
<column>
<property name="text">
<string>Server DHT Key</string>
</property>
</column>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="removePushButton">
<property name="text">
<string>Remove Server</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="mainVSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -29,11 +29,13 @@
#include <iostream>
#include <retroshare/rsbanlist.h>
#include <retroshare/rsconfig.h>
#include <retroshare/rsdht.h>
#include <retroshare/rspeers.h>
#include <retroshare/rsturtle.h>
#include <retroshare/rsbanlist.h>
#include <QCheckBox>
#include <QMovie>
#include <QMenu>
#include <QTcpSocket>
@ -170,6 +172,32 @@ ServerPage::ServerPage(QWidget * parent, Qt::WindowFlags flags)
connect(ui.totalDownloadRate,SIGNAL(valueChanged(int)),this,SLOT(saveRates()));
connect(ui.totalUploadRate, SIGNAL(valueChanged(int)),this,SLOT(saveRates()));
//Relay Tab
QObject::connect(ui.noFriendSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateRelayOptions()));
QObject::connect(ui.noFOFSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateRelayOptions()));
QObject::connect(ui.noGeneralSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateRelayOptions()));
QObject::connect(ui.bandFriendSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateRelayOptions()));
QObject::connect(ui.bandFOFSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateRelayOptions()));
QObject::connect(ui.bandGeneralSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateRelayOptions()));
QObject::connect(ui.addPushButton,SIGNAL(clicked()),this,SLOT(addServer()));
QObject::connect(ui.removePushButton,SIGNAL(clicked()),this,SLOT(removeServer()));
QObject::connect(ui.DhtLineEdit,SIGNAL(textChanged(const QString &)),this,SLOT(checkKey()));
QObject::connect(ui.enableCheckBox,SIGNAL(stateChanged(int)),this,SLOT(updateEnabled()));
QObject::connect(ui.serverCheckBox,SIGNAL(stateChanged(int)),this,SLOT(updateEnabled()));
QObject::connect(ui.noFriendSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateTotals()));
QObject::connect(ui.bandFriendSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateTotals()));
QObject::connect(ui.noFOFSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateTotals()));
QObject::connect(ui.bandFOFSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateTotals()));
QObject::connect(ui.noGeneralSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateTotals()));
QObject::connect(ui.bandGeneralSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateTotals()));
QObject::connect(ui.enableCheckBox,SIGNAL(toggled(bool)),this,SLOT(updateRelayMode()));
QObject::connect(ui.serverCheckBox,SIGNAL(toggled(bool)),this,SLOT(updateRelayMode()));
}
void ServerPage::saveAndTestInProxy()
@ -373,6 +401,49 @@ void ServerPage::load()
updateOutProxyIndicator();
}
//Relay Tab
uint32_t count;
uint32_t bandwidth;
rsDht->getRelayAllowance(RSDHT_RELAY_CLASS_FRIENDS, count, bandwidth);
whileBlocking(ui.noFriendSpinBox)->setValue(count);
whileBlocking(ui.bandFriendSpinBox)->setValue(bandwidth / 1024);
rsDht->getRelayAllowance(RSDHT_RELAY_CLASS_FOF, count, bandwidth);
whileBlocking(ui.noFOFSpinBox)->setValue(count);
whileBlocking(ui.bandFOFSpinBox)->setValue(bandwidth / 1024);
rsDht->getRelayAllowance(RSDHT_RELAY_CLASS_GENERAL, count, bandwidth);
whileBlocking(ui.noGeneralSpinBox)->setValue(count);
whileBlocking(ui.bandGeneralSpinBox)->setValue(bandwidth / 1024);
updateTotals();
uint32_t relayMode = rsDht->getRelayMode();
if (relayMode & RSDHT_RELAY_ENABLED)
{
whileBlocking(ui.enableCheckBox)->setCheckState(Qt::Checked);
if ((relayMode & RSDHT_RELAY_MODE_MASK) == RSDHT_RELAY_MODE_OFF)
{
whileBlocking(ui.serverCheckBox)->setCheckState(Qt::Unchecked);
}
else
{
whileBlocking(ui.serverCheckBox)->setCheckState(Qt::Checked);
}
}
else
{
whileBlocking(ui.enableCheckBox)->setCheckState(Qt::Unchecked);
whileBlocking(ui.serverCheckBox)->setCheckState(Qt::Unchecked);
}
loadServers();
updateRelayOptions();
updateEnabled();
checkKey();
}
void ServerPage::toggleAutoIncludeFriends(bool b)
@ -1006,7 +1077,7 @@ void ServerPage::loadHiddenNode()
whileBlocking(ui.hiddenpage_serviceAddress)->setText(QString::fromStdString(detail.hiddenNodeAddress));
whileBlocking(ui.hiddenpage_servicePort) -> setValue(detail.hiddenNodePort);
/* in I2P there is no port - there is only the address */
whileBlocking(ui.hiddenpage_servicePort)->setEnabled(detail.hiddenType != RS_HIDDEN_TYPE_I2P);
whileBlocking(ui.hiddenpage_servicePort)->setHidden(detail.hiddenType == RS_HIDDEN_TYPE_I2P);
/* out proxy settings */
std::string proxyaddr;
@ -1635,7 +1706,7 @@ void ServerPage::updateStatusBob()
ui.pbBobStart->setToolTip("BOB is not accessible");
ui.pbBobRestart->setEnabled(false);
ui.pbBobRestart->setToolTip("BOB is not accessible");
ui.pbBobStop->setEnabled(false);
// don't disable the stop button! (in case bob is running you are otherwise unable to stop and disable it)
ui.pbBobStop->setToolTip("BOB is not accessible");
} else {
ui.pbBobStart->setToolTip("");
@ -1732,3 +1803,161 @@ void ServerPage::handleNetworkReply(QNetworkReply *reply)
reply->close();
}
//#####################################################################
//## Relay Tab
//#####################################################################
void ServerPage::updateTotals()
{
int nFriends = ui.noFriendSpinBox->value();
int friendBandwidth = ui.bandFriendSpinBox->value();
int nFOF = ui.noFOFSpinBox->value();
int fofBandwidth = ui.bandFOFSpinBox->value();
int nGeneral = ui.noGeneralSpinBox->value();
int genBandwidth = ui.bandGeneralSpinBox->value();
int total = nFriends + nFOF + nGeneral;
rsDht->setRelayAllowance(RSDHT_RELAY_CLASS_ALL, total, 0);
rsDht->setRelayAllowance(RSDHT_RELAY_CLASS_FRIENDS, nFriends, 1024 * friendBandwidth);
rsDht->setRelayAllowance(RSDHT_RELAY_CLASS_FOF, nFOF, 1024 * fofBandwidth);
rsDht->setRelayAllowance(RSDHT_RELAY_CLASS_GENERAL, nGeneral, 1024 * genBandwidth);
}
/** Saves the changes on this page */
void ServerPage::updateRelayMode()
{
uint32_t relayMode = 0;
if (ui.enableCheckBox->isChecked())
{
relayMode |= RSDHT_RELAY_ENABLED;
if (ui.serverCheckBox->isChecked())
{
relayMode |= RSDHT_RELAY_MODE_ON;
}
else
{
relayMode |= RSDHT_RELAY_MODE_OFF;
}
}
else
{
relayMode |= RSDHT_RELAY_MODE_OFF;
}
rsDht->setRelayMode(relayMode);
}
void ServerPage::loadServers()
{
std::list<std::string> servers;
std::list<std::string>::iterator it;
rsDht->getRelayServerList(servers);
ui.serverTreeWidget->clear();
for(it = servers.begin(); it != servers.end(); ++it)
{
QTreeWidgetItem *item = new QTreeWidgetItem();
item->setData(0, Qt::DisplayRole, QString::fromStdString(*it));
ui.serverTreeWidget->addTopLevelItem(item);
}
}
void ServerPage::updateRelayOptions()
{
int nFriends = ui.noFriendSpinBox->value();
int friendBandwidth = ui.bandFriendSpinBox->value();
int nFOF = ui.noFOFSpinBox->value();
int fofBandwidth = ui.bandFOFSpinBox->value();
int nGeneral = ui.noGeneralSpinBox->value();
int genBandwidth = ui.bandGeneralSpinBox->value();
ui.totalFriendLineEdit->setText(QString::number(nFriends * friendBandwidth * 2));
ui.totalFOFLineEdit->setText(QString::number(nFOF * fofBandwidth * 2));
ui.totalGeneralLineEdit->setText(QString::number(nGeneral * genBandwidth * 2));
ui.totalBandwidthLineEdit->setText(QString::number((nFriends * friendBandwidth + nFOF * fofBandwidth + nGeneral * genBandwidth) * 2));
ui.noTotalLineEdit->setText(QString::number(nFriends + nFOF + nGeneral));
}
void ServerPage::updateEnabled()
{
std::cerr << "RelayPage::updateEnabled()" << std::endl;
if (ui.enableCheckBox->isChecked())
{
ui.relayOptionGBox->setEnabled(true);
if (ui.serverCheckBox->isChecked())
{
std::cerr << "RelayPage::updateEnabled() Both Enabled" << std::endl;
ui.serverGroupBox->setEnabled(true);
}
else
{
std::cerr << "RelayPage::updateEnabled() Options Only Enabled" << std::endl;
ui.serverGroupBox->setEnabled(false);
}
}
else
{
std::cerr << "RelayPage::updateEnabled() Both Disabled" << std::endl;
ui.relayOptionGBox->setEnabled(false);
ui.serverGroupBox->setEnabled(false);
}
}
void ServerPage::checkKey()
{
std::string server = ui.DhtLineEdit->text().toStdString();
std::cerr << "RelayPage::checkKey() length: " << server.length();
std::cerr << std::endl;
if (server.length() == 40)
{
ui.keyOkBox->setChecked(true);
}
else
{
ui.keyOkBox->setChecked(false);
}
}
void ServerPage::addServer()
{
std::cerr << "RelayPage::addServer()";
std::cerr << std::endl;
if (!ui.keyOkBox->isChecked())
{
return;
}
std::string server = ui.DhtLineEdit->text().toStdString();
bool ok = rsDht->addRelayServer(server);
if (ok)
{
ui.DhtLineEdit->setText(QString(""));
}
loadServers();
}
void ServerPage::removeServer()
{
QTreeWidgetItem *item = ui.serverTreeWidget->currentItem();
if (item)
{
std::string server = item->data(0, Qt::DisplayRole).toString().toStdString();
rsDht->removeRelayServer(server);
}
loadServers();
}

View File

@ -114,6 +114,16 @@ private slots:
void connectionWithoutCert();
//Relay Tab
void updateRelayOptions();
void updateEnabled();
void checkKey();
void addServer();
void removeServer();
void loadServers();
void updateTotals();
void updateRelayMode();
// autoProxyCallback interface
public:
void taskFinished(taskTicket *&ticket);

View File

@ -811,7 +811,7 @@ behind a firewall or a VPN.</string>
<attribute name="title">
<string>Hidden Service Configuration</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<layout class="QHBoxLayout" name="tabHiddenConfHLayout">
<item>
<widget class="QTabWidget" name="hiddenServiceTab">
<property name="sizePolicy">
@ -827,7 +827,7 @@ behind a firewall or a VPN.</string>
<attribute name="title">
<string>Outgoing Manual Tor/I2P</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<layout class="QVBoxLayout" name="hiddenServiceTabManualVLayout">
<item>
<widget class="QLabel" name="hiddenpage_outHeader">
<property name="text">
@ -836,7 +836,7 @@ behind a firewall or a VPN.</string>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_4">
<layout class="QGridLayout" name="hiddenpage_proxyOKHLayoutGLayout">
<item row="0" column="2">
<widget class="QSpinBox" name="hiddenpage_proxyPort_tor">
<property name="toolTip">
@ -996,9 +996,9 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why
<attribute name="title">
<string>Automatic I2P/BOB</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_12">
<layout class="QVBoxLayout" name="hiddenServiceTabI2PBOBVLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<layout class="QHBoxLayout" name="bobHLayout">
<item>
<widget class="QCheckBox" name="cb_enableBob">
<property name="text">
@ -1007,7 +1007,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<spacer name="bobHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
@ -1036,9 +1036,9 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why
<property name="title">
<string>I2P Basic Open Bridge</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<layout class="QVBoxLayout" name="gbBobVLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_21">
<layout class="QHBoxLayout" name="i2pBobHLayout">
<property name="topMargin">
<number>0</number>
</property>
@ -1046,74 +1046,70 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_22">
<widget class="QLabel" name="i2pInstAddLabel">
<property name="text">
<string>I2P Instance address</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="hiddenpage_proxyAddress_i2p_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="placeholderText">
<string>127.0.0.1</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="i2pProxyPortLabel">
<property name="text">
<string>I2P proxy port</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="hiddenpage_proxyPort_i2p_2">
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="bobAccHLayout">
<item>
<widget class="QLabel" name="label_17">
<widget class="QLabel" name="iconlabel_i2p_outgoing_2">
<property name="text">
<string>I2P Instance address</string>
<string/>
</property>
<property name="pixmap">
<pixmap resource="../images.qrc">:/images/ledoff1.png</pixmap>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="hiddenpage_proxyAddress_i2p_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<widget class="QLabel" name="bobAccLabel">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This led is green when the port listen on the left is active on your computer. It does not&lt;/p&gt;&lt;p&gt;mean that your Retroshare traffic transits though I2P. It will do so only if &lt;/p&gt;&lt;p&gt;you connect to Hidden nodes, or if you are running a Hidden node yourself.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="placeholderText">
<string>127.0.0.1</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_22">
<property name="text">
<string>I2P proxy port</string>
<string>BOB accessible</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="hiddenpage_proxyPort_i2p_2">
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_23">
<item>
<widget class="QLabel" name="iconlabel_i2p_outgoing_2">
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../images.qrc">:/images/ledoff1.png</pixmap>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_18">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This led is green when the port listen on the left is active on your computer. It does not&lt;/p&gt;&lt;p&gt;mean that your Retroshare traffic transits though I2P. It will do so only if &lt;/p&gt;&lt;p&gt;you connect to Hidden nodes, or if you are running a Hidden node yourself.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>BOB accessible</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_14">
<layout class="QHBoxLayout" name="bobB32AddrHLayout">
<item>
<widget class="QLabel" name="lBobB32Addr">
<property name="sizePolicy">
@ -1161,10 +1157,10 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why
<bool>true</bool>
</property>
<property name="currentIndex">
<number>0</number>
<number>1</number>
</property>
<widget class="QWidget" name="page">
<layout class="QVBoxLayout" name="verticalLayout_9">
<widget class="QWidget" name="gbBobSimplePage">
<layout class="QVBoxLayout" name="gbBobSimplePageVLayout">
<item>
<widget class="QPlainTextEdit" name="pteBobSimple">
<property name="sizePolicy">
@ -1193,14 +1189,14 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why
</item>
</layout>
</widget>
<widget class="QWidget" name="gbBobAdvancedPage1">
<layout class="QVBoxLayout" name="verticalLayout_8">
<widget class="QWidget" name="gbBobAdvancedPage">
<layout class="QVBoxLayout" name="gbBobAdvancedPageVLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout_7">
<layout class="QVBoxLayout" name="bobAdvTunnelVLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_13">
<layout class="QHBoxLayout" name="bobAdvTunLenHLayout">
<item>
<widget class="QLabel" name="label_13">
<widget class="QLabel" name="bobAdvTunLenLabel">
<property name="text">
<string>Tunnel length (in/out)</string>
</property>
@ -1241,9 +1237,9 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<layout class="QHBoxLayout" name="bobAdvTunQuaHLayout">
<item>
<widget class="QLabel" name="label_21">
<widget class="QLabel" name="bobAdvTunQuaLabel">
<property name="text">
<string>Tunnel quantity (in/out)</string>
</property>
@ -1290,9 +1286,9 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<layout class="QHBoxLayout" name="bobAdvTunVarHLayout">
<item>
<widget class="QLabel" name="label_16">
<widget class="QLabel" name="bobAdvTunVarLabel">
<property name="text">
<string>Tunnel variance (in/out)</string>
</property>
@ -1338,11 +1334,11 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_13">
<layout class="QVBoxLayout" name="bobAdvServKeyVLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_25">
<layout class="QHBoxLayout" name="bobAdvServKeyHLayout">
<item>
<widget class="QLabel" name="label_20">
<widget class="QLabel" name="bobAdvServKeyLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
@ -1355,7 +1351,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<spacer name="bobAdvServKeyHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
@ -1399,9 +1395,9 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_24">
<layout class="QHBoxLayout" name="bobToolBarHLayout">
<item>
<spacer name="horizontalSpacer_4">
<spacer name="bobToolBarHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
@ -1457,7 +1453,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<spacer name="gbBobVSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
@ -1475,7 +1471,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why
<attribute name="title">
<string>Incoming</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QVBoxLayout" name="hiddenServiceTabIncomingVLayout">
<item>
<widget class="QLabel" name="hiddenpage_inHeader">
<property name="text">
@ -1548,7 +1544,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why
</widget>
</item>
<item row="1" column="3">
<layout class="QHBoxLayout" name="horizontalLayout">
<layout class="QHBoxLayout" name="serviceIncomingHLayout">
<item>
<widget class="QLabel" name="iconlabel_service_incoming">
<property name="maximumSize">
@ -1673,6 +1669,436 @@ If you have issues connecting over Tor check the Tor logs too.</string>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabRelay">
<attribute name="title">
<string>Relay</string>
</attribute>
<layout class="QVBoxLayout" name="RelayPageVLayout">
<item>
<layout class="QHBoxLayout" name="relayTopHLayout">
<item>
<widget class="QCheckBox" name="enableCheckBox">
<property name="text">
<string>Enable Relay Connections</string>
</property>
</widget>
</item>
<item>
<spacer name="relayTopLeftHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="serverCheckBox">
<property name="text">
<string>Use Relay Servers</string>
</property>
</widget>
</item>
<item>
<spacer name="relayTopRightHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="relayOptionGBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="title">
<string>Relay options</string>
</property>
<layout class="QGridLayout" name="relayOptionGBoxGLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<spacer name="optionHeaderLHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>110</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<widget class="QLabel" name="headerNumberLabel">
<property name="text">
<string>Number</string>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="optionHeaderRHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>6</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="3">
<widget class="QLabel" name="headerBandwidthLabel">
<property name="text">
<string>Bandwidth per link</string>
</property>
</widget>
</item>
<item row="0" column="4" rowspan="7">
<widget class="Line" name="totalVLine">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QLabel" name="headerTotalLabel">
<property name="text">
<string>Total Bandwidth</string>
</property>
</widget>
</item>
<item row="1" column="0" rowspan="2">
<widget class="QLabel" name="friendLabel">
<property name="text">
<string>Friends</string>
</property>
</widget>
</item>
<item row="1" column="1" rowspan="2">
<widget class="QSpinBox" name="noFriendSpinBox">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>99</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="1" column="2" rowspan="2">
<widget class="QLabel" name="xFriendLabel">
<property name="text">
<string notr="true">x</string>
</property>
</widget>
</item>
<item row="1" column="3" rowspan="2">
<widget class="QSpinBox" name="bandFriendSpinBox">
<property name="suffix">
<string>kB/s</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
<item row="2" column="5">
<widget class="QLineEdit" name="totalFriendLineEdit">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0" rowspan="2">
<widget class="QLabel" name="fofLabel">
<property name="text">
<string>Friends of Friends</string>
</property>
</widget>
</item>
<item row="3" column="1" rowspan="2">
<widget class="QSpinBox" name="noFOFSpinBox">
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
<item row="3" column="2" rowspan="2">
<widget class="QLabel" name="xFOFLabel">
<property name="text">
<string notr="true">x</string>
</property>
</widget>
</item>
<item row="3" column="3" rowspan="2">
<widget class="QSpinBox" name="bandFOFSpinBox">
<property name="suffix">
<string>kB/s</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
<item row="4" column="5">
<widget class="QLineEdit" name="totalFOFLineEdit">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="0" rowspan="2">
<widget class="QLabel" name="generalLabel">
<property name="text">
<string>General</string>
</property>
</widget>
</item>
<item row="5" column="1" rowspan="2">
<widget class="QSpinBox" name="noGeneralSpinBox">
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
<item row="5" column="2" rowspan="2">
<widget class="QLabel" name="xGeneralLabel">
<property name="text">
<string notr="true">x</string>
</property>
</widget>
</item>
<item row="5" column="3" rowspan="2">
<widget class="QSpinBox" name="bandGeneralSpinBox">
<property name="suffix">
<string>kB/s</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
<item row="6" column="5">
<widget class="QLineEdit" name="totalGeneralLineEdit">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="7" column="0" colspan="6">
<widget class="Line" name="totalHLine">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="totalLabel">
<property name="text">
<string>Total:</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLineEdit" name="noTotalLineEdit">
<property name="focusPolicy">
<enum>Qt::WheelFocus</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="8" column="2" colspan="2">
<spacer name="totalHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>123</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="8" column="5">
<widget class="QLineEdit" name="totalBandwidthLineEdit">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="9" column="0" colspan="6">
<widget class="QLabel" name="warningLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true"> border: 1px solid #DCDC41;
border-radius: 6px;
background: #FFFFD7;
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2);
</string>
</property>
<property name="text">
<string>Warning: This bandwidth adds up to the max bandwidth.</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="serverGroupBox">
<property name="title">
<string>Relay Server Setup</string>
</property>
<layout class="QGridLayout" name="serverGroupBoxGLayout">
<item row="0" column="0">
<widget class="QLineEdit" name="DhtLineEdit">
<property name="inputMask">
<string notr="true">HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="keyOkBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string/>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="addPushButton">
<property name="text">
<string>Add Server</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QTreeWidget" name="serverTreeWidget">
<column>
<property name="text">
<string>Server DHT Key</string>
</property>
</column>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="removePushButton">
<property name="text">
<string>Remove Server</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="relayHelpLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true"> border: 1px solid #DCDC41;
border-radius: 6px;
background: #FFFFD7;
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2);
</string>
</property>
<property name="text">
<string>&lt;p&gt;By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.&lt;/p&gt;
&lt;p&gt;You may choose to act as a relay by checking &lt;i&gt;enable relay connections&lt;/i&gt;, or simply benefit from other peers acting as relay, by checking &lt;i&gt;use relay servers&lt;/i&gt;. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.&lt;/p&gt;
&lt;p&gt;In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.&lt;/p&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="relayVSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>

View File

@ -43,6 +43,7 @@ TransferPage::TransferPage(QWidget * parent, Qt::WindowFlags flags)
QObject::connect(ui._e2e_encryption_CB,SIGNAL(activated(int)),this,SLOT(updateEncryptionPolicy(int))) ;
QObject::connect(ui._diskSpaceLimit_SB,SIGNAL(valueChanged(int)),this,SLOT(updateDiskSizeLimit(int))) ;
QObject::connect(ui._max_tr_up_per_sec_SB, SIGNAL( valueChanged( int ) ), this, SLOT( updateMaxTRUpRate(int) ) );
QObject::connect(ui._filePermDirectDL_CB,SIGNAL(activated(int)),this,SLOT(updateFilePermDirectDL(int)));
QObject::connect(ui.incomingButton, SIGNAL(clicked( bool ) ), this , SLOT( setIncomingDirectory() ) );
QObject::connect(ui.partialButton, SIGNAL(clicked( bool ) ), this , SLOT( setPartialsDirectory() ) );
@ -77,6 +78,16 @@ void TransferPage::updateEncryptionPolicy(int b)
}
}
void TransferPage::updateFilePermDirectDL(int i)
{
switch (i)
{
case 0: rsFiles->setFilePermDirectDL(RS_FILE_PERM_DIRECT_DL_YES); break;
case 1: rsFiles->setFilePermDirectDL(RS_FILE_PERM_DIRECT_DL_NO); break;
default: rsFiles->setFilePermDirectDL(RS_FILE_PERM_DIRECT_DL_PER_USER); break;
}
}
void TransferPage::load()
{
whileBlocking(ui.shareDownloadDirectoryCB)->setChecked(rsFiles->getShareDownloadDirectory());
@ -107,6 +118,13 @@ void TransferPage::load()
whileBlocking(ui._diskSpaceLimit_SB)->setValue(rsFiles->freeDiskSpaceLimit()) ;
whileBlocking(ui._max_tr_up_per_sec_SB)->setValue(rsTurtle->getMaxTRForwardRate()) ;
whileBlocking(ui._max_up_SB)->setValue(rsFiles->getMaxUploadSlotsPerFriend()) ;
switch (rsFiles->filePermDirectDL())
{
case RS_FILE_PERM_DIRECT_DL_YES: whileBlocking(ui._filePermDirectDL_CB)->setCurrentIndex(0) ; break ;
case RS_FILE_PERM_DIRECT_DL_NO: whileBlocking(ui._filePermDirectDL_CB)->setCurrentIndex(1) ; break ;
default: whileBlocking(ui._filePermDirectDL_CB)->setCurrentIndex(2) ; break ;
}
}
void TransferPage::updateDefaultStrategy(int i)

View File

@ -46,9 +46,10 @@ class TransferPage: public ConfigPage
void updateQueueSize(int) ;
void updateDefaultStrategy(int) ;
void updateDiskSizeLimit(int) ;
void updateMaxTRUpRate(int);
void updateEncryptionPolicy(int);
void updateMaxTRUpRate(int);
void updateEncryptionPolicy(int);
void updateMaxUploadSlots(int);
void updateFilePermDirectDL(int);
void editDirectories() ;
void setIncomingDirectory();

View File

@ -10,15 +10,15 @@
<height>1099</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<layout class="QVBoxLayout" name="TransferPageVLayout">
<item>
<widget class="QGroupBox" name="groupBox_4">
<widget class="QGroupBox" name="sharedGBox">
<property name="title">
<string>Shared Directories</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QVBoxLayout" name="sharedGBoxVLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<layout class="QHBoxLayout" name="shareDownloadHLayout">
<item>
<widget class="QCheckBox" name="shareDownloadDirectoryCB">
<property name="enabled">
@ -42,10 +42,7 @@
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<layout class="QHBoxLayout" name="autoCheckDirectoriesHLayout">
<item>
<widget class="QCheckBox" name="autoCheckDirectories_CB">
<property name="text">
@ -75,27 +72,31 @@
</layout>
</item>
<item>
<widget class="QCheckBox" name="followSymLinks_CB">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Tells Retroshare to follow the links. Loops and duplicate directories are automatically taken care of. If unchecked, Retroshare will just ignore symbolic links to both files and directories.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>follow symbolic links</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
<layout class="QHBoxLayout" name="followSymLinksHLayout">
<item>
<widget class="QCheckBox" name="followSymLinks_CB">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Tells Retroshare to follow the links. Loops and duplicate directories are automatically taken care of. If unchecked, Retroshare will just ignore symbolic links to both files and directories.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>follow symbolic links</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<widget class="QGroupBox" name="incomingGBox">
<property name="title">
<string>Incoming Directory</string>
</property>
<layout class="QGridLayout" name="_3">
<layout class="QGridLayout" name="incomingGBoxGLayout">
<item row="0" column="0">
<widget class="QLineEdit" name="incomingDir">
<property name="readOnly">
@ -139,11 +140,11 @@
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<widget class="QGroupBox" name="partialGBox">
<property name="title">
<string>Partials Directory</string>
</property>
<layout class="QGridLayout" name="_2">
<layout class="QGridLayout" name="partialGBoxGLayout">
<item row="0" column="0">
<widget class="QLineEdit" name="partialsDir">
<property name="readOnly">
@ -187,61 +188,68 @@
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<widget class="QGroupBox" name="transfertGBox">
<property name="title">
<string>Transfer options</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<layout class="QVBoxLayout" name="transfertGBoxVLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<layout class="QHBoxLayout" name="transfertHLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<layout class="QVBoxLayout" name="transfertLabelVLayout">
<item>
<widget class="QLabel" name="label">
<widget class="QLabel" name="_queueSize_Label">
<property name="text">
<string>Maximum simultaneous downloads:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_5">
<widget class="QLabel" name="_max_up_Label">
<property name="text">
<string>Maximum uploads per friend (0 = no limit)</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_3">
<widget class="QLabel" name="_defaultStrategy_Label">
<property name="text">
<string>Default chunk strategy:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<widget class="QLabel" name="_diskSpaceLimit_Label">
<property name="text">
<string>Safety disk space limit :</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_6">
<widget class="QLabel" name="_max_tr_up_per_sec_Label">
<property name="text">
<string>Max. tunnel req. forwarded per second:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4">
<widget class="QLabel" name="_e2e_encryption_Label">
<property name="text">
<string>End-to-end encryption:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="_filePermDirectDL_Label">
<property name="text">
<string>Allow direct download:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<layout class="QVBoxLayout" name="transfertValuesVLayout">
<item>
<widget class="QSpinBox" name="_queueSize_SB">
<property name="enabled">
@ -344,6 +352,28 @@
</item>
</widget>
</item>
<item>
<widget class="QComboBox" name="_filePermDirectDL_CB">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;How RS manage direct download setting.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<item>
<property name="text">
<string>Yes</string>
</property>
</item>
<item>
<property name="text">
<string>No</string>
</property>
</item>
<item>
<property name="text">
<string>Per user</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
</layout>

View File

@ -32,7 +32,6 @@
#include "FileAssociationsPage.h"
#include "SoundPage.h"
#include "TransferPage.h"
#include "RelayPage.h"
#include "ChatPage.h"
#include "ChannelPage.h"
#include "PeoplePage.h"
@ -156,7 +155,6 @@ SettingsPage::initStackedWidget()
addPage(new ForumPage()); // FORUMS
addPage(new PostedPage()); // POSTED RENAME TO LINKS
addPage(new NotifyPage()); // NOTIFY
addPage(new RelayPage() ); // RELAY SHOUD BE INSIDE NETWORK AS A TAB
addPage(new PluginsPage() ); // PLUGINS
addPage(new AppearancePage()); // APPEARENCE
addPage(new SoundPage() ); // SOUND

View File

@ -1066,7 +1066,7 @@ void RshareSettings::setForumLoadEmoticons(bool value)
/* Channel */
bool RshareSettings::getChannelLoadThread()
{
return valueFromGroup("Channel", "LoadThread", true).toBool();
return valueFromGroup("Channel", "LoadThread", false).toBool();
}
void RshareSettings::setChannelLoadThread(bool value)

View File

@ -60,6 +60,7 @@
#define COL_GROUP_SIZE_MSGS 2
#define COL_GROUP_SUBSCRIBED 3
#define COL_GROUP_POPULARITY 4
#define COL_GROUP_UNIQUE_ID 5
static const int PARTIAL_VIEW_SIZE = 9 ;
static const int MAX_TUNNEL_REQUESTS_DISPLAY = 10 ;
@ -70,10 +71,10 @@ static const int GXSTRANS_STATISTICS_DELAY_BETWEEN_GROUP_REQ = 30 ; // never req
#define GXSTRANS_GROUP_STAT 0x03
#define GXSTRANS_MSG_META 0x04
#define DEBUG_GXSTRANS_STATS 1
//#define DEBUG_GXSTRANS_STATS 1
GxsTransportStatistics::GxsTransportStatistics(QWidget *parent)
: RsAutoUpdatePage(2000,parent)
: RsGxsUpdateBroadcastPage(rsGxsTrans,parent)
{
setupUi(this) ;
@ -93,6 +94,7 @@ GxsTransportStatistics::GxsTransportStatistics(QWidget *parent)
// load settings
processSettings(true);
updateDisplay(true);
}
GxsTransportStatistics::~GxsTransportStatistics()
@ -139,19 +141,15 @@ void GxsTransportStatistics::CustomPopupMenu( QPoint )
contextMnu.exec(QCursor::pos());
}
void GxsTransportStatistics::updateDisplay()
void GxsTransportStatistics::updateDisplay(bool)
{
time_t now = time(NULL) ;
time_t now = time(NULL) ;
#ifdef DEBUG_GXSTRANS_STATS
std::cerr << "GxsTransportStatistics::updateDisplay()" << std::endl;
#endif
if(mLastGroupReqTS + GXSTRANS_STATISTICS_DELAY_BETWEEN_GROUP_REQ < now)
{
requestGroupMeta();
mLastGroupReqTS = now ;
}
//_tst_CW->updateContent() ;
updateContent();
requestGroupMeta();
mLastGroupReqTS = now ;
}
QString GxsTransportStatistics::getPeerName(const RsPeerId &peer_id)
@ -199,7 +197,6 @@ void GxsTransportStatistics::updateContent()
rsGxsTrans->getStatistics(transinfo) ;
// clear
treeWidget->clear();
@ -246,32 +243,57 @@ void GxsTransportStatistics::updateContent()
if(groupTreeWidget->isItemExpanded(groupTreeWidget->topLevelItem(i)))
openned_groups.insert(RsGxsGroupId(groupTreeWidget->topLevelItem(i)->data(COL_GROUP_GRP_ID,Qt::DisplayRole).toString().toStdString())) ;
groupTreeWidget->clear();
groupTreeWidget->clear();
for(std::map<RsGxsGroupId,RsGxsTransGroupStatistics>::const_iterator it(mGroupStats.begin());it!=mGroupStats.end();++it)
{
const RsGxsTransGroupStatistics& stat(it->second) ;
QTreeWidgetItem *item ;
{
QString unique_id = QString::fromStdString(stat.mGrpId.toStdString());
QList<QTreeWidgetItem*> iteml = groupTreeWidget->findItems(unique_id,Qt::MatchExactly,COL_GROUP_UNIQUE_ID) ;
if(iteml.empty())
item = new QTreeWidgetItem;
else
item = *iteml.begin();
}
QTreeWidgetItem *item = new QTreeWidgetItem();
groupTreeWidget->addTopLevelItem(item);
groupTreeWidget->setItemExpanded(item,openned_groups.find(it->first) != openned_groups.end());
item->setData(COL_GROUP_GRP_ID, Qt::DisplayRole, QString::fromStdString(stat.mGrpId.toStdString())) ;
item->setData(COL_GROUP_NUM_MSGS, Qt::DisplayRole, QString::number(stat.mNumMsgs)) ;
QString msg_time_string = (stat.last_publish_TS>0)?QString(" (Last msg: %1)").arg(QDateTime::fromTime_t(stat.last_publish_TS).toString()):"" ;
item->setData(COL_GROUP_NUM_MSGS, Qt::DisplayRole, QString::number(stat.mNumMsgs) + msg_time_string) ;
item->setData(COL_GROUP_GRP_ID, Qt::DisplayRole, QString::fromStdString(it->first.toStdString())) ;
item->setData(COL_GROUP_SIZE_MSGS, Qt::DisplayRole, QString::number(stat.mTotalSizeOfMsgs)) ;
item->setData(COL_GROUP_SUBSCRIBED,Qt::DisplayRole, stat.subscribed?tr("Yes"):tr("No")) ;
item->setData(COL_GROUP_POPULARITY,Qt::DisplayRole, QString::number(stat.popularity)) ;
item->setData(COL_GROUP_UNIQUE_ID, Qt::DisplayRole, QString::fromStdString(it->first.toStdString())) ;
for(uint32_t i=0;i<it->second.messages_metas.size();++i)
for(std::map<RsGxsMessageId,RsMsgMetaData>::const_iterator msgIt(stat.messages_metas.begin());msgIt!=stat.messages_metas.end();++msgIt)
{
QTreeWidgetItem *sitem = new QTreeWidgetItem(item) ;
const RsMsgMetaData& meta(msgIt->second);
const RsMsgMetaData& meta(it->second.messages_metas[i]) ;
QTreeWidgetItem *sitem ;
{
QString unique_id = QString::fromStdString(meta.mMsgId.toStdString());
QList<QTreeWidgetItem*> iteml = groupTreeWidget->findItems(unique_id,Qt::MatchExactly,COL_GROUP_UNIQUE_ID) ;
if(iteml.empty())
sitem = new QTreeWidgetItem(item) ;
else
sitem = *iteml.begin();
}
GxsIdLabel *label = new GxsIdLabel();
label->setId(meta.mAuthorId) ;
groupTreeWidget->setItemWidget(sitem,COL_GROUP_GRP_ID,label) ;
sitem->setData(COL_GROUP_UNIQUE_ID, Qt::DisplayRole,QString::fromStdString(meta.mMsgId.toStdString()));
sitem->setData(COL_GROUP_NUM_MSGS,Qt::DisplayRole, QDateTime::fromTime_t(meta.mPublishTs).toString());
}
}
@ -319,6 +341,8 @@ void GxsTransportStatistics::loadRequest(const TokenQueue *queue, const TokenReq
std::cerr << std::endl;
break;
}
updateContent();
}
void GxsTransportStatistics::requestGroupMeta()
@ -330,8 +354,6 @@ void GxsTransportStatistics::requestGroupMeta()
std::cerr << std::endl;
#endif
mTransQueue->cancelActiveRequestTokens(GXSTRANS_GROUP_META);
RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_GROUP_META;
@ -340,7 +362,6 @@ void GxsTransportStatistics::requestGroupMeta()
}
void GxsTransportStatistics::requestGroupStat(const RsGxsGroupId &groupId)
{
mTransQueue->cancelActiveRequestTokens(GXSTRANS_GROUP_STAT);
uint32_t token;
rsGxsTrans->getTokenService()->requestGroupStatistic(token, groupId);
mTransQueue->queueRequest(token, 0, RS_TOKREQ_ANSTYPE_ACK, GXSTRANS_GROUP_STAT);
@ -354,8 +375,6 @@ void GxsTransportStatistics::requestMsgMeta(const RsGxsGroupId& grpId)
std::cerr << std::endl;
#endif
mTransQueue->cancelActiveRequestTokens(GXSTRANS_MSG_META);
RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_MSG_META;
@ -369,12 +388,12 @@ void GxsTransportStatistics::requestMsgMeta(const RsGxsGroupId& grpId)
void GxsTransportStatistics::loadGroupStat(const uint32_t &token)
{
#ifdef DEBUG_GXSTRANS_STATS
std::cerr << "GxsTransportStatistics::loadGroupStat." << std::endl;
#endif
GxsGroupStatistic stats;
rsGxsTrans->getGroupStatistic(token, stats);
#ifdef DEBUG_GXSTRANS_STATS
std::cerr << "Loading group stats: " << stats.mGrpId << ", num msgs=" << stats.mNumMsgs << ", total size=" << stats.mTotalSizeOfMsgs << std::endl;
#endif
dynamic_cast<GxsGroupStatistic&>(mGroupStats[stats.mGrpId]) = stats ;
}
@ -417,6 +436,7 @@ void GxsTransportStatistics::loadGroupMeta(const uint32_t& token)
RsGxsTransGroupStatistics& s(mGroupStats[vit->mGroupId]);
s.popularity = vit->mPop ;
s.subscribed = IS_GROUP_SUBSCRIBED(vit->mSubscribeFlags) ;
s.mGrpId = vit->mGroupId ;
}
// remove group stats for group that do not exist anymore
@ -438,6 +458,7 @@ void GxsTransportStatistics::loadMsgMeta(const uint32_t& token)
return ;
for(GxsMsgMetaMap::const_iterator it(m.begin());it!=m.end();++it)
mGroupStats[it->first].messages_metas = it->second ;
for(uint32_t i=0;i<it->second.size();++i)
mGroupStats[it->first].addMessageMeta(it->first,it->second[i]) ;
}

View File

@ -30,6 +30,7 @@
#include "util/TokenQueue.h"
#include "RsAutoUpdatePage.h"
#include "ui_GxsTransportStatistics.h"
#include "gui/gxs/RsGxsUpdateBroadcastPage.h"
class GxsTransportStatisticsWidget ;
class UIStateHelper;
@ -37,15 +38,29 @@ class UIStateHelper;
class RsGxsTransGroupStatistics: public GxsGroupStatistic
{
public:
RsGxsTransGroupStatistics() {}
RsGxsTransGroupStatistics()
{
last_publish_TS = 0;
popularity = 0;
subscribed = false;
}
void addMessageMeta(const RsGxsGroupId& grp,const RsMsgMetaData& meta)
{
messages_metas[meta.mMsgId] = meta ;
last_publish_TS = std::max(last_publish_TS,meta.mPublishTs) ;
mGrpId = grp ;
}
bool subscribed ;
int popularity ;
std::vector<RsMsgMetaData> messages_metas ;
time_t last_publish_TS;
std::map<RsGxsMessageId,RsMsgMetaData> messages_metas ;
};
class GxsTransportStatistics: public RsAutoUpdatePage, public TokenResponse, public Ui::GxsTransportStatistics
class GxsTransportStatistics: public RsGxsUpdateBroadcastPage, public TokenResponse, public Ui::GxsTransportStatistics
{
Q_OBJECT
@ -66,6 +81,7 @@ private slots:
void personDetails();
private:
void updateDisplay(bool complete) ;
void loadGroupMeta(const uint32_t& token);
void loadGroupStat(const uint32_t& token);
void loadMsgMeta(const uint32_t& token);
@ -77,8 +93,6 @@ private:
void processSettings(bool bLoad);
bool m_bProcessSettings;
virtual void updateDisplay() ;
GxsTransportStatisticsWidget *_tst_CW ;
TokenQueue *mTransQueue ;
UIStateHelper *mStateHelper;

View File

@ -7,64 +7,33 @@
<x>0</x>
<y>0</y>
<width>1468</width>
<height>659</height>
<height>779</height>
</rect>
</property>
<property name="windowTitle">
<string>Router Statistics</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Gxs Transport Groups:</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QTreeWidget" name="groupTreeWidget">
<column>
<property name="text">
<string>Group ID / Author</string>
</property>
</column>
<column>
<property name="text">
<string>Number of messages / Publish TS</string>
</property>
</column>
<column>
<property name="text">
<string>Total size of messages</string>
</property>
</column>
<column>
<property name="text">
<string>Subscribed</string>
</property>
</column>
<column>
<property name="text">
<string>Popularity</string>
</property>
</column>
</widget>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>GroupBox</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QTreeWidget" name="treeWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
@ -114,6 +83,49 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Gxs Transport Groups:</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QTreeWidget" name="groupTreeWidget">
<column>
<property name="text">
<string>Group ID / Author</string>
</property>
</column>
<column>
<property name="text">
<string>Number of messages / Publish TS</string>
</property>
</column>
<column>
<property name="text">
<string>Local size of data</string>
</property>
</column>
<column>
<property name="text">
<string>Subscribed</string>
</property>
</column>
<column>
<property name="text">
<string>Popularity</string>
</property>
</column>
</widget>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>

View File

@ -142,7 +142,7 @@ void TurtleRouterDialog::updateTunnelRequests( const std::vector<std::vector<std
num /= 1024.0f,++k;
sprintf(tmp,"%3.2f %s",num,units[k].c_str()) ;
QString str = tr("Tunnel id") + ": " + QString::fromUtf8(tunnels_info[i][0].c_str()) + "\t [" + QString::fromUtf8(tunnels_info[i][2].c_str()) + "] --> [" + QString::fromUtf8(tunnels_info[i][1].c_str()) + "]\t\t " + tr("last transfer") + ": " + QString::fromStdString(tunnels_info[i][4]) + " " + "\t " + tr("Speed") + ": " + QString::fromStdString(tmp) ;
QString str = tr("Tunnel id") + ": " + QString::fromUtf8(tunnels_info[i][0].c_str()) + "\t" + tr("Speed") + ": " + QString::fromStdString(tmp) + "\t " + tr("last transfer") + ": " + QString::fromStdString(tunnels_info[i][4])+ "\t" + QString::fromUtf8(tunnels_info[i][2].c_str()) + " -> " + QString::fromUtf8(tunnels_info[i][1].c_str());
stl.clear() ;
stl.push_back(str) ;
QTreeWidgetItem *item = new QTreeWidgetItem(stl);

View File

@ -460,7 +460,6 @@ HEADERS += rshare.h \
gui/settings/ChatPage.h \
gui/settings/ChannelPage.h \
gui/settings/PostedPage.h \
gui/settings/RelayPage.h \
gui/settings/ServicePermissionsPage.h \
gui/settings/AddFileAssociationDialog.h \
gui/settings/GroupFrameSettingsWidget.h \
@ -551,6 +550,7 @@ HEADERS += rshare.h \
gui/NewsFeed.h \
gui/feeds/FeedItem.h \
gui/feeds/FeedHolder.h \
gui/feeds/GxsCircleItem.h \
gui/feeds/PeerItem.h \
gui/feeds/MsgItem.h \
gui/feeds/ChatMsgItem.h \
@ -642,7 +642,6 @@ FORMS += gui/StartDialog.ui \
gui/settings/ChatPage.ui \
gui/settings/ChannelPage.ui \
gui/settings/PostedPage.ui \
gui/settings/RelayPage.ui \
gui/settings/ServicePermissionsPage.ui \
gui/settings/PluginItem.ui \
gui/settings/GroupFrameSettingsWidget.ui \
@ -656,6 +655,7 @@ FORMS += gui/StartDialog.ui \
gui/advsearch/AdvancedSearchDialog.ui \
gui/advsearch/expressionwidget.ui \
gui/NewsFeed.ui \
gui/feeds/GxsCircleItem.ui \
gui/feeds/PeerItem.ui \
gui/feeds/MsgItem.ui \
gui/feeds/ChatMsgItem.ui \
@ -685,7 +685,7 @@ FORMS += gui/StartDialog.ui \
gui/statistics/StatisticsWindow.ui \
gui/statistics/BwCtrlWindow.ui \
gui/statistics/RttStatistics.ui \
gui/GetStartedDialog.ui \
gui/GetStartedDialog.ui
# gui/ForumsDialog.ui \
@ -868,7 +868,6 @@ SOURCES += main.cpp \
gui/settings/ChatPage.cpp \
gui/settings/ChannelPage.cpp \
gui/settings/PostedPage.cpp \
gui/settings/RelayPage.cpp \
gui/settings/ServicePermissionsPage.cpp \
gui/settings/AddFileAssociationDialog.cpp \
gui/settings/GroupFrameSettingsWidget.cpp \
@ -900,6 +899,7 @@ SOURCES += main.cpp \
gui/NewsFeed.cpp \
gui/feeds/FeedItem.cpp \
gui/feeds/FeedHolder.cpp \
gui/feeds/GxsCircleItem.cpp \
gui/feeds/PeerItem.cpp \
gui/feeds/MsgItem.cpp \
gui/feeds/ChatMsgItem.cpp \

View File

@ -50,15 +50,15 @@ Item
var radix = JSON.parse(par.response).data.cert_string
var name = mainWindow.user_name
var encodedName = UriJs.URI.encode(name)
ClipboardWrapper.postToClipBoard(
var nodeUrl = (
"retroshare://certificate?" +
"name=" + encodedName +
"&radix=" + UriJs.URI.encode(radix) +
"&location=" + encodedName
)
"&location=" + encodedName )
ClipboardWrapper.postToClipBoard(nodeUrl)
linkCopiedPopup.itemName = name
linkCopiedPopup.open()
platformGW.shareUrl(nodeUrl);
})
}
}

View File

@ -0,0 +1,76 @@
/*
* RetroShare Android QML App
* Copyright (C) 2017 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.7
Item
{
id: compRoot
property string gxs_id
height: 130
width: height
////////////// The following should be considered privates /////////////////////
property bool has_avatar: false
property int avatarAttemptCnt: 0
function getDetails()
{
++compRoot.avatarAttemptCnt
rsApi.request(
"/identity/get_identity_details",
JSON.stringify({ gxs_id: compRoot.gxs_id }),
function(par)
{
var jData = JSON.parse(par.response).data
setDetails(jData)
if(!compRoot.has_avatar &&
compRoot.avatarAttemptCnt < 3) getDetails()
})
}
function setDetails(data)
{
compRoot.has_avatar = data.avatar.length > 0
if(compRoot.has_avatar)
{
contactAvatar.source =
"data:image/png;base64," + data.avatar
}
}
Component.onCompleted: if(visible && !has_avatar) getDetails()
onVisibleChanged: if(visible && !has_avatar) getDetails()
Image
{
id: contactAvatar
anchors.fill: parent
visible: compRoot.has_avatar
}
ColorHash
{
anchors.fill: parent
visible: !compRoot.has_avatar
hash: compRoot.gxs_id
}
}

View File

@ -58,21 +58,20 @@ Item
}
ColorHash
AvatarOrColorHash
{
id: colorHash
id: topFace
gxs_id: cntDt.md.gxs_id
anchors.top: parent.top
anchors.topMargin: 6
anchors.horizontalCenter: parent.horizontalCenter
height: 150
hash: cntDt.md.gxs_id
}
Column
{
anchors.top: colorHash.bottom
anchors.top: topFace.bottom
anchors.topMargin: 6
anchors.horizontalCenter: parent.horizontalCenter
@ -84,6 +83,13 @@ Item
anchors.horizontalCenter: parent.horizontalCenter
spacing: 6
ColorHash
{
hash: cntDt.md.gxs_id
height: parent.height - 10
anchors.verticalCenter: parent.verticalCenter
}
Text
{
text: cntDt.md.name
@ -92,7 +98,6 @@ Item
Image
{
source: cntDt.is_contact ?
"qrc:/icons/rating.png" :
"qrc:/icons/rating-unrated.png"
@ -149,16 +154,18 @@ Item
function(par)
{
var jD = JSON.parse(par.response).data
ClipboardWrapper.postToClipBoard(
var contactUrl = (
"retroshare://" +
"identity?gxsid=" +
cntDt.md.gxs_id +
"&name=" +
UriJs.URI.encode(cntDt.md.name) +
"&groupdata=" +
UriJs.URI.encode(jD.radix))
UriJs.URI.encode(jD.radix) )
ClipboardWrapper.postToClipBoard(contactUrl)
linkCopiedPopup.itemName = cntDt.md.name
linkCopiedPopup.visible = true
platformGW.shareUrl(contactUrl);
}
)
}

View File

@ -73,6 +73,17 @@ public class RetroShareQmlActivity extends QtActivity
if (uri != null) NativeCalls.notifyIntentUri(uri);
}
@UsedByNativeCode @SuppressWarnings("unused")
public void shareUrl(String urlStr)
{
Intent shareIntent = new Intent()
.setAction(Intent.ACTION_SEND)
.putExtra(Intent.EXTRA_TEXT, urlStr)
.setType("text/plain");
startActivity(Intent.createChooser(shareIntent,"")); // TODO: Need proper title?
}
private boolean isMyServiceRunning(Class<?> serviceClass)
{
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);

View File

@ -0,0 +1,41 @@
/*
* RetroShare Android QML App
* Copyright (C) 2017 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "androidplatforminteracions.h"
#include <QtAndroid>
#include <QtAndroidExtras/QAndroidJniObject>
AndroidPlatformInteracions::AndroidPlatformInteracions(QObject *parent) :
PlatformInteracions(parent) {}
void AndroidPlatformInteracions::shareUrl(QUrl url)
{
QString encUri = url.toString(QUrl::FullyEncoded);
QAndroidJniObject uriStr = QAndroidJniObject::fromString(encUri);
QtAndroid::runOnAndroidThread(
[uriStr]()
{
QtAndroid::androidActivity()
.callMethod<void>(
"shareUrl",
"(Ljava/lang/String;)V",
uriStr.object<jstring>());
});
}

View File

@ -0,0 +1,34 @@
#pragma once
/*
* RetroShare Android QML App
* Copyright (C) 2017 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QObject>
#include <QUrl>
#include "platforminteracions.h"
class AndroidPlatformInteracions : public PlatformInteracions
{
Q_OBJECT
public:
explicit AndroidPlatformInteracions(QObject *parent = nullptr);
public slots:
virtual void shareUrl(QUrl url);
};

View File

@ -0,0 +1,25 @@
/*
* RetroShare Android QML App
* Copyright (C) 2017 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "defaultplatforminteracions.h"
DefaultPlatformInteracions::DefaultPlatformInteracions(QObject *parent) :
PlatformInteracions(parent) {}
// Do nothing as the url is pasted to clipboard directly in QML
void DefaultPlatformInteracions::shareUrl(QUrl /*url*/) {}

View File

@ -0,0 +1,34 @@
#pragma once
/*
* RetroShare Android QML App
* Copyright (C) 2017 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QObject>
#include <QUrl>
#include "platforminteracions.h"
class DefaultPlatformInteracions : public PlatformInteracions
{
Q_OBJECT
public:
explicit DefaultPlatformInteracions(QObject *parent = nullptr);
public slots:
virtual void shareUrl(QUrl url);
};

View File

@ -30,12 +30,16 @@
# include <QtAndroid>
# include <QtAndroidExtras/QAndroidJniObject>
# include <atomic>
# include "androidplatforminteracions.h"
#else
# include "defaultplatforminteracions.h"
#endif // Q_OS_ANDROID
#include "libresapilocalclient.h"
#include "rsqmlappengine.h"
#include "androidimagepicker.h"
#include "platforminteracions.h"
int main(int argc, char *argv[])
{
@ -71,6 +75,8 @@ int main(int argc, char *argv[])
#ifdef Q_OS_ANDROID
rootContext.setContextProperty("Q_OS_ANDROID", QVariant(true));
AndroidPlatformInteracions platformGW(&app);
/* Add Activity Intent data to args, because onNewIntent is called only if
* the Intet was triggered when the Activity was already created, so only in
* case onCreate is not called.
@ -125,10 +131,12 @@ int main(int argc, char *argv[])
if(!uriStr.isEmpty()) mainArgs.append(uriStr);
#else
DefaultPlatformInteracions platformGW(&app);
rootContext.setContextProperty("Q_OS_ANDROID", QVariant(false));
#endif
rootContext.setContextProperty("mainArgs", mainArgs);
rootContext.setContextProperty("platformGW", &platformGW);
#ifdef QT_DEBUG
rootContext.setContextProperty("QT_DEBUG", QVariant(true));

View File

@ -0,0 +1,32 @@
#pragma once
/*
* RetroShare Android QML App
* Copyright (C) 2017 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QObject>
#include <QUrl>
class PlatformInteracions : public QObject
{
Q_OBJECT
public:
explicit PlatformInteracions(QObject *parent = nullptr) : QObject(parent) {}
public slots:
virtual void shareUrl(QUrl url) = 0;
};

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