llgroupmgr.cpp 66 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594
  1. /**
  2. * @file llgroupmgr.cpp
  3. * @brief LLGroupMgr class implementation
  4. *
  5. * $LicenseInfo:firstyear=2004&license=viewergpl$
  6. *
  7. * Copyright (c) 2004-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. /**
  33. * Manager for aggregating all client knowledge for specific groups
  34. * Keeps a cache of group information.
  35. */
  36. #include "llviewerprecompiledheaders.h"
  37. #include "llgroupmgr.h"
  38. #include "llcorehttputil.h"
  39. #include "lleconomy.h"
  40. #include "llinstantmessage.h"
  41. #include "llnotifications.h"
  42. #include "lltransactiontypes.h"
  43. #include "lluictrlfactory.h"
  44. #include "roles_constants.h"
  45. #include "llagent.h"
  46. #include "llappviewer.h" // For gFrameTimeSeconds
  47. #include "llfloatergroupinfo.h"
  48. #include "hbfloatersearch.h"
  49. #include "llstartup.h" // For gMaxAgentGroups
  50. #include "llstatusbar.h"
  51. #include "llviewercontrol.h"
  52. #include "llviewermessage.h" // For send_improved_im()
  53. LLGroupMgr gGroupMgr;
  54. // Was 32, but we can now pertain to 70 groups in SL, so... HB
  55. constexpr U32 MAX_CACHED_GROUPS = 72;
  56. ///////////////////////////////////////////////////////////////////////////////
  57. // Group invitation callback (was formerly in llviewermessage.cpp).
  58. ///////////////////////////////////////////////////////////////////////////////
  59. void join_group_response_coro(const std::string& url, LLUUID group_id,
  60. bool accepted_invite)
  61. {
  62. LLSD payload;
  63. payload["group"] = group_id;
  64. LLCoreHttpUtil::HttpCoroutineAdapter adapter("GroupInvitationResponse");
  65. LLSD result = adapter.postAndSuspend(url, payload);
  66. LLCore::HttpStatus status =
  67. LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(result);
  68. if (!status || !result.has("success") || !result["success"].asBoolean())
  69. {
  70. llwarns << "Error responding via capability to invitation to group: "
  71. << group_id << ". Error: " << status.toString() << llendl;
  72. // *TODO: implement UDP fallback ?
  73. return;
  74. }
  75. if (accepted_invite)
  76. {
  77. // Refresh all group information
  78. gAgent.sendAgentDataUpdateRequest();
  79. gGroupMgr.clearGroupData(group_id);
  80. // Refresh the floater for this group, if any.
  81. LLFloaterGroupInfo::refreshGroup(group_id);
  82. // Refresh the group panel of the search window, if necessary.
  83. HBFloaterSearch::refreshGroup(group_id);
  84. }
  85. }
  86. bool join_group_response(const LLSD& notification, const LLSD& response)
  87. {
  88. S32 option = LLNotification::getSelectedOption(notification, response);
  89. bool accept_invite = false;
  90. const LLSD& payload = notification["payload"];
  91. LLUUID group_id = payload["group_id"].asUUID();
  92. LLUUID transaction_id = payload["transaction_id"].asUUID();
  93. std::string name = payload["name"].asString();
  94. std::string message = payload["message"].asString();
  95. S32 fee = payload["fee"].asInteger();
  96. bool use_cap = payload.has("use_offline_cap") &&
  97. payload["use_offline_cap"].asBoolean();
  98. if (option == 2 && group_id.notNull())
  99. {
  100. LLFloaterGroupInfo::showFromUUID(group_id);
  101. LLSD args;
  102. args["MESSAGE"] = message;
  103. gNotifications.add("JoinGroup", args, payload);
  104. return false;
  105. }
  106. if (option == 0 && group_id.notNull())
  107. {
  108. // Check for promotion or demotion.
  109. S32 max_groups = gMaxAgentGroups;
  110. if (gAgent.isInGroup(group_id))
  111. {
  112. ++max_groups;
  113. }
  114. if ((S32)gAgent.mGroups.size() < max_groups)
  115. {
  116. accept_invite = true;
  117. }
  118. else
  119. {
  120. LLSD args;
  121. args["NAME"] = name;
  122. args["INVITE"] = message;
  123. gNotifications.add("JoinedTooManyGroupsMember", args, payload);
  124. }
  125. }
  126. if (accept_invite && fee > 0)
  127. {
  128. // If there is a fee to join this group, make sure the user does want
  129. // to join.
  130. LLSD args;
  131. args["COST"] = llformat("%d", fee);
  132. // Set the fee for next time to 0, so that we do not keep asking about
  133. // a fee.
  134. LLSD next_payload = notification["payload"];
  135. next_payload["fee"] = 0;
  136. gNotifications.add("JoinGroupCanAfford", args, next_payload);
  137. }
  138. else if (use_cap)
  139. {
  140. const std::string& url =
  141. gAgent.getRegionCapability(accept_invite ? "AcceptGroupInvite"
  142. : "DeclineGroupInvite");
  143. if (url.empty())
  144. {
  145. llwarns << "Missing capability, cannot reply to offline group invitation to group: "
  146. << group_id << llendl;
  147. return false;
  148. }
  149. gCoros.launch("groupInvitationResponse",
  150. boost::bind(&join_group_response_coro, url, group_id,
  151. accept_invite));
  152. }
  153. else
  154. {
  155. send_improved_im(group_id, "name", "message", IM_ONLINE,
  156. accept_invite ? IM_GROUP_INVITATION_ACCEPT
  157. :IM_GROUP_INVITATION_DECLINE,
  158. transaction_id);
  159. }
  160. return false;
  161. }
  162. static LLNotificationFunctorRegistration jgr_1("JoinGroup",
  163. join_group_response);
  164. static LLNotificationFunctorRegistration jgr_2("JoinedTooManyGroupsMember",
  165. join_group_response);
  166. static LLNotificationFunctorRegistration jgr_3("JoinGroupCanAfford",
  167. join_group_response);
  168. //
  169. // LLRoleActionSet
  170. //
  171. LLRoleActionSet::LLRoleActionSet()
  172. : mActionSetData(NULL)
  173. {
  174. }
  175. LLRoleActionSet::~LLRoleActionSet()
  176. {
  177. delete mActionSetData;
  178. std::for_each(mActions.begin(), mActions.end(), DeletePointer());
  179. mActions.clear();
  180. }
  181. //
  182. // LLGroupMemberData
  183. //
  184. LLGroupMemberData::LLGroupMemberData(const LLUUID& id,
  185. S32 contribution,
  186. U64 agent_powers,
  187. const std::string& title,
  188. const std::string& online_status,
  189. bool is_owner)
  190. : mID(id),
  191. mContribution(contribution),
  192. mAgentPowers(agent_powers),
  193. mTitle(title),
  194. mOnlineStatus(online_status),
  195. mIsOwner(is_owner)
  196. {
  197. }
  198. void LLGroupMemberData::addRole(const LLUUID& role, LLGroupRoleData* rd)
  199. {
  200. mRolesList[role] = rd;
  201. }
  202. bool LLGroupMemberData::removeRole(const LLUUID& role)
  203. {
  204. role_list_t::iterator it = mRolesList.find(role);
  205. if (it != mRolesList.end())
  206. {
  207. mRolesList.hmap_erase(it);
  208. return true;
  209. }
  210. return false;
  211. }
  212. //
  213. // LLGroupRoleData
  214. //
  215. LLGroupRoleData::LLGroupRoleData(const LLUUID& role_id,
  216. const std::string& role_name,
  217. const std::string& role_title,
  218. const std::string& role_desc,
  219. U64 role_powers, S32 member_count)
  220. : mRoleID(role_id),
  221. mMemberCount(member_count),
  222. mMembersNeedsSort(false)
  223. {
  224. mRoleData.mRoleName = role_name;
  225. mRoleData.mRoleTitle = role_title;
  226. mRoleData.mRoleDescription = role_desc;
  227. mRoleData.mRolePowers = role_powers;
  228. mRoleData.mChangeType = RC_UPDATE_NONE;
  229. }
  230. LLGroupRoleData::LLGroupRoleData(const LLUUID& role_id, LLRoleData role_data,
  231. S32 member_count)
  232. : mRoleID(role_id),
  233. mRoleData(role_data),
  234. mMemberCount(member_count),
  235. mMembersNeedsSort(false)
  236. {
  237. }
  238. S32 LLGroupRoleData::getMembersInRole(uuid_vec_t members, bool needs_sort)
  239. {
  240. if (mRoleID.isNull())
  241. {
  242. // This is the everyone role, just return the size of members,
  243. // because everyone is in the everyone role.
  244. return members.size();
  245. }
  246. // Sort the members list, if needed.
  247. if (mMembersNeedsSort)
  248. {
  249. std::sort(mMemberIDs.begin(), mMemberIDs.end());
  250. mMembersNeedsSort = false;
  251. }
  252. if (needs_sort)
  253. {
  254. // Sort the members parameter.
  255. std::sort(members.begin(), members.end());
  256. }
  257. // Return the number of members in the intersection.
  258. S32 max_size = llmin(members.size(), mMemberIDs.size());
  259. uuid_vec_t in_role(max_size);
  260. uuid_vec_t::iterator in_role_end;
  261. in_role_end = std::set_intersection(mMemberIDs.begin(), mMemberIDs.end(),
  262. members.begin(), members.end(),
  263. in_role.begin());
  264. return in_role_end - in_role.begin();
  265. }
  266. void LLGroupRoleData::addMember(const LLUUID& member)
  267. {
  268. mMembersNeedsSort = true;
  269. mMemberIDs.emplace_back(member);
  270. }
  271. bool LLGroupRoleData::removeMember(const LLUUID& member)
  272. {
  273. uuid_vec_t::iterator it = std::find(mMemberIDs.begin(), mMemberIDs.end(),
  274. member);
  275. if (it != mMemberIDs.end())
  276. {
  277. mMembersNeedsSort = true;
  278. mMemberIDs.erase(it);
  279. return true;
  280. }
  281. return false;
  282. }
  283. void LLGroupRoleData::clearMembers()
  284. {
  285. mMembersNeedsSort = false;
  286. mMemberIDs.clear();
  287. }
  288. //
  289. // LLGroupMgrGroupData
  290. //
  291. LLGroupMgrGroupData::LLGroupMgrGroupData(const LLUUID& id)
  292. : mID(id),
  293. mShowInList(true),
  294. mOpenEnrollment(false),
  295. mMembershipFee(0),
  296. mAllowPublish(false),
  297. mListInProfile(false),
  298. mMaturePublish(false),
  299. mChanged(false),
  300. mMemberCount(0),
  301. mRoleCount(0),
  302. mReceivedRoleMemberPairs(0),
  303. mMemberDataComplete(false),
  304. mRoleDataComplete(false),
  305. mRoleMemberDataComplete(false),
  306. mGroupPropertiesDataComplete(false),
  307. mPendingRoleMemberRequest(false),
  308. mAccessTime(0.0f)
  309. {
  310. }
  311. void LLGroupMgrGroupData::setAccessed()
  312. {
  313. mAccessTime = (F32)LLFrameTimer::getTotalSeconds();
  314. }
  315. bool LLGroupMgrGroupData::getRoleData(const LLUUID& role_id,
  316. LLRoleData& role_data)
  317. {
  318. // Do we have changes for it ?
  319. role_data_map_t::const_iterator it = mRoleChanges.find(role_id);
  320. if (it != mRoleChanges.end())
  321. {
  322. if (it->second.mChangeType == RC_DELETE)
  323. {
  324. return false;
  325. }
  326. role_data = it->second;
  327. return true;
  328. }
  329. // Ok, no changes, has not been deleted, is not a new role, just find the
  330. // role.
  331. role_list_t::const_iterator rit = mRoles.find(role_id);
  332. if (rit != mRoles.end())
  333. {
  334. role_data = rit->second->getRoleData();
  335. return true;
  336. }
  337. // This role must not exist.
  338. return false;
  339. }
  340. void LLGroupMgrGroupData::setRoleData(const LLUUID& role_id,
  341. LLRoleData role_data)
  342. {
  343. // If this is a newly created group, we need to change the data in the
  344. // created list.
  345. role_data_map_t::iterator it = mRoleChanges.find(role_id);
  346. if (it != mRoleChanges.end())
  347. {
  348. if (it->second.mChangeType == RC_CREATE)
  349. {
  350. role_data.mChangeType = RC_CREATE;
  351. mRoleChanges[role_id] = role_data;
  352. return;
  353. }
  354. else if (it->second.mChangeType == RC_DELETE)
  355. {
  356. // Don't do anything for a role being deleted.
  357. return;
  358. }
  359. }
  360. // Not a new role, so put it in the changes list.
  361. LLRoleData old_role_data;
  362. role_list_t::iterator rit = mRoles.find(role_id);
  363. if (rit != mRoles.end())
  364. {
  365. bool data_change =
  366. rit->second->mRoleData.mRoleDescription !=
  367. role_data.mRoleDescription ||
  368. rit->second->mRoleData.mRoleName != role_data.mRoleName ||
  369. rit->second->mRoleData.mRoleTitle != role_data.mRoleTitle;
  370. bool powers_change =
  371. rit->second->mRoleData.mRolePowers != role_data.mRolePowers;
  372. if (!data_change && !powers_change)
  373. {
  374. // We are back to the original state, the changes have been
  375. // 'undone' so take out the change.
  376. mRoleChanges.erase(role_id);
  377. return;
  378. }
  379. if (data_change && powers_change)
  380. {
  381. role_data.mChangeType = RC_UPDATE_ALL;
  382. }
  383. else if (data_change)
  384. {
  385. role_data.mChangeType = RC_UPDATE_DATA;
  386. }
  387. else
  388. {
  389. role_data.mChangeType = RC_UPDATE_POWERS;
  390. }
  391. mRoleChanges[role_id] = role_data;
  392. }
  393. else
  394. {
  395. llwarns << "Change being made to non-existant role " << role_id
  396. << llendl;
  397. }
  398. }
  399. // This is a no-op if the role has already been created.
  400. void LLGroupMgrGroupData::createRole(const LLUUID& role_id,
  401. LLRoleData role_data)
  402. {
  403. if (mRoleChanges.count(role_id))
  404. {
  405. llwarns << "Attempt to create a role for existing role " << role_id
  406. << ". Aborted." << llendl;
  407. }
  408. else
  409. {
  410. role_data.mChangeType = RC_CREATE;
  411. mRoleChanges[role_id] = role_data;
  412. }
  413. }
  414. void LLGroupMgrGroupData::deleteRole(const LLUUID& role_id)
  415. {
  416. // If this was a new role, just discard it.
  417. role_data_map_t::iterator it = mRoleChanges.find(role_id);
  418. if (it != mRoleChanges.end() && it->second.mChangeType == RC_CREATE)
  419. {
  420. mRoleChanges.erase(it);
  421. return;
  422. }
  423. LLRoleData rd;
  424. rd.mChangeType = RC_DELETE;
  425. mRoleChanges[role_id] = rd;
  426. }
  427. void LLGroupMgrGroupData::addRolePower(const LLUUID& role_id, U64 power)
  428. {
  429. LLRoleData rd;
  430. if (getRoleData(role_id, rd))
  431. {
  432. rd.mRolePowers |= power;
  433. setRoleData(role_id, rd);
  434. }
  435. else
  436. {
  437. llwarns << "addRolePower: no role data found for " << role_id
  438. << llendl;
  439. }
  440. }
  441. void LLGroupMgrGroupData::removeRolePower(const LLUUID& role_id, U64 power)
  442. {
  443. LLRoleData rd;
  444. if (getRoleData(role_id, rd))
  445. {
  446. rd.mRolePowers &= ~power;
  447. setRoleData(role_id, rd);
  448. }
  449. else
  450. {
  451. llwarns << "removeRolePower: no role data found for " << role_id
  452. << llendl;
  453. }
  454. }
  455. U64 LLGroupMgrGroupData::getRolePowers(const LLUUID& role_id)
  456. {
  457. LLRoleData rd;
  458. if (getRoleData(role_id, rd))
  459. {
  460. return rd.mRolePowers;
  461. }
  462. else
  463. {
  464. llwarns << "getRolePowers: no role data found for " << role_id
  465. << llendl;
  466. return GP_NO_POWERS;
  467. }
  468. }
  469. void LLGroupMgrGroupData::removeData()
  470. {
  471. // Remove member data first, because removeRoleData will walk the member
  472. // list
  473. removeMemberData();
  474. removeRoleData();
  475. }
  476. void LLGroupMgrGroupData::removeMemberData()
  477. {
  478. for (member_list_t::iterator mi = mMembers.begin(), end = mMembers.end();
  479. mi != end; ++mi)
  480. {
  481. delete mi->second;
  482. }
  483. mMembers.clear();
  484. mMemberDataComplete = false;
  485. }
  486. void LLGroupMgrGroupData::removeRoleData()
  487. {
  488. for (member_list_t::iterator it = mMembers.begin(), end = mMembers.end();
  489. it != end; ++it)
  490. {
  491. LLGroupMemberData* data = it->second;
  492. if (data)
  493. {
  494. data->clearRoles();
  495. }
  496. }
  497. for (role_list_t::iterator it = mRoles.begin(), end = mRoles.end();
  498. it != end; ++it)
  499. {
  500. LLGroupRoleData* data = it->second;
  501. if (data)
  502. {
  503. delete data;
  504. }
  505. }
  506. mRoles.clear();
  507. mReceivedRoleMemberPairs = 0;
  508. mRoleDataComplete = false;
  509. mRoleMemberDataComplete = false;
  510. }
  511. void LLGroupMgrGroupData::removeRoleMemberData()
  512. {
  513. for (member_list_t::iterator it = mMembers.begin(), end = mMembers.end();
  514. it != end; ++it)
  515. {
  516. LLGroupMemberData* data = it->second;
  517. if (data)
  518. {
  519. data->clearRoles();
  520. }
  521. }
  522. for (role_list_t::iterator it = mRoles.begin(), end = mRoles.end();
  523. it != end; ++it)
  524. {
  525. LLGroupRoleData* data = it->second;
  526. if (data)
  527. {
  528. data->clearMembers();
  529. }
  530. }
  531. mReceivedRoleMemberPairs = 0;
  532. mRoleMemberDataComplete = false;
  533. }
  534. LLGroupMgrGroupData::~LLGroupMgrGroupData()
  535. {
  536. removeData();
  537. }
  538. bool LLGroupMgrGroupData::changeRoleMember(const LLUUID& role_id,
  539. const LLUUID& member_id,
  540. LLRoleMemberChangeType rmc)
  541. {
  542. role_list_t::iterator ri = mRoles.find(role_id);
  543. if (ri == mRoles.end())
  544. {
  545. llwarns << "Could not find role " << role_id << llendl;
  546. return false;
  547. }
  548. member_list_t::iterator mi = mMembers.find(member_id);
  549. if (mi == mMembers.end())
  550. {
  551. llwarns << "Could not find member " << member_id << llendl;
  552. return false;
  553. }
  554. LLGroupRoleData* grd = ri->second;
  555. LLGroupMemberData* gmd = mi->second;
  556. if (!grd || !gmd)
  557. {
  558. llwarns << "Could not get member or role data." << llendl;
  559. return false;
  560. }
  561. if (rmc == RMC_ADD)
  562. {
  563. llinfos << "Adding member " << member_id << " to role " << role_id
  564. << llendl;
  565. grd->addMember(member_id);
  566. gmd->addRole(role_id, grd);
  567. // TODO move this into addrole function
  568. // see if they added someone to the owner role and update isOwner
  569. gmd->mIsOwner = gmd->mIsOwner || role_id == mOwnerRole;
  570. }
  571. else if (rmc == RMC_REMOVE)
  572. {
  573. llinfos << "Removing member " << member_id << " from role " << role_id
  574. << llendl;
  575. grd->removeMember(member_id);
  576. gmd->removeRole(role_id);
  577. // see if they removed someone from the owner role and update isOwner
  578. gmd->mIsOwner = gmd->mIsOwner && role_id != mOwnerRole;
  579. }
  580. lluuid_pair role_member;
  581. role_member.first = role_id;
  582. role_member.second = member_id;
  583. change_map_t::iterator it = mRoleMemberChanges.find(role_member);
  584. if (it != mRoleMemberChanges.end())
  585. {
  586. // There was already a role change for this role_member
  587. if (it->second.mChange == rmc)
  588. {
  589. // Already recorded this change? Weird.
  590. llinfos << "Received duplicate change for "
  591. << " role: " << role_id << " member " << member_id
  592. << " change " << (rmc == RMC_ADD ? "ADD" : "REMOVE")
  593. << llendl;
  594. }
  595. // The only two operations (add and remove) currently cancel each other
  596. // out. If that changes this will need more logic
  597. else if (rmc == RMC_NONE)
  598. {
  599. llwarns << "Existing entry with 'RMC_NONE' change ! This should not happen."
  600. << llendl;
  601. LLRoleMemberChange rc(role_id, member_id, rmc);
  602. mRoleMemberChanges[role_member] = rc;
  603. }
  604. else
  605. {
  606. mRoleMemberChanges.erase(it);
  607. }
  608. }
  609. else
  610. {
  611. LLRoleMemberChange rc(role_id, member_id, rmc);
  612. mRoleMemberChanges[role_member] = rc;
  613. }
  614. recalcAgentPowers(member_id);
  615. mChanged = true;
  616. return true;
  617. }
  618. void LLGroupMgrGroupData::recalcAllAgentPowers()
  619. {
  620. for (member_list_t::iterator mit = mMembers.begin(), end = mMembers.end();
  621. mit != end; ++mit)
  622. {
  623. LLGroupMemberData* gmd = mit->second;
  624. if (!gmd) continue;
  625. gmd->mAgentPowers = 0;
  626. for (LLGroupMemberData::role_list_t::iterator it = gmd->mRolesList.begin(),
  627. end2 = gmd->mRolesList.end();
  628. it != end2; ++it)
  629. {
  630. LLGroupRoleData* grd = it->second;
  631. if (!grd) continue;
  632. gmd->mAgentPowers |= grd->mRoleData.mRolePowers;
  633. }
  634. }
  635. }
  636. void LLGroupMgrGroupData::recalcAgentPowers(const LLUUID& agent_id)
  637. {
  638. member_list_t::iterator mi = mMembers.find(agent_id);
  639. if (mi == mMembers.end()) return;
  640. LLGroupMemberData* gmd = mi->second;
  641. if (!gmd) return;
  642. gmd->mAgentPowers = 0;
  643. for (LLGroupMemberData::role_list_t::iterator it = gmd->mRolesList.begin(),
  644. end = gmd->mRolesList.end();
  645. it != end; ++it)
  646. {
  647. LLGroupRoleData* grd = it->second;
  648. if (grd)
  649. {
  650. gmd->mAgentPowers |= grd->mRoleData.mRolePowers;
  651. }
  652. }
  653. }
  654. bool packRoleUpdateMessageBlock(LLMessageSystem* msg,
  655. const LLUUID& group_id, const LLUUID& role_id,
  656. const LLRoleData& role_data,
  657. bool start_message)
  658. {
  659. if (start_message)
  660. {
  661. msg->newMessage(_PREHASH_GroupRoleUpdate);
  662. msg->nextBlock(_PREHASH_AgentData);
  663. msg->addUUID(_PREHASH_AgentID,gAgentID);
  664. msg->addUUID(_PREHASH_SessionID,gAgentSessionID);
  665. msg->addUUID(_PREHASH_GroupID,group_id);
  666. start_message = false;
  667. }
  668. msg->nextBlock(_PREHASH_RoleData);
  669. msg->addUUID(_PREHASH_RoleID, role_id);
  670. msg->addString(_PREHASH_Name, role_data.mRoleName);
  671. msg->addString(_PREHASH_Description, role_data.mRoleDescription);
  672. msg->addString(_PREHASH_Title, role_data.mRoleTitle);
  673. msg->addU64(_PREHASH_Powers, role_data.mRolePowers);
  674. msg->addU8(_PREHASH_UpdateType, (U8)role_data.mChangeType);
  675. if (msg->isSendFullFast())
  676. {
  677. gAgent.sendReliableMessage();
  678. start_message = true;
  679. }
  680. return start_message;
  681. }
  682. void LLGroupMgrGroupData::sendRoleChanges()
  683. {
  684. // Commit changes locally
  685. bool start_message = true;
  686. bool need_role_cleanup = false;
  687. bool need_role_data = false;
  688. bool need_power_recalc = false;
  689. // Apply all changes
  690. role_list_t::iterator role_it, role_end;
  691. for (role_data_map_t::iterator iter = mRoleChanges.begin();
  692. iter != mRoleChanges.end(); )
  693. {
  694. role_data_map_t::iterator it = iter++; // safely increment iter
  695. const LLUUID& role_id = it->first;
  696. const LLRoleData& role_data = it->second;
  697. // Commit to local data set
  698. role_it = mRoles.find(it->first);
  699. role_end = mRoles.end();
  700. if ((role_it == role_end && role_data.mChangeType != RC_CREATE) ||
  701. (role_it != role_end && role_data.mChangeType == RC_CREATE))
  702. {
  703. continue;
  704. }
  705. // NOTE: role_it is valid EXCEPT for the RC_CREATE case
  706. switch (role_data.mChangeType)
  707. {
  708. case RC_CREATE:
  709. {
  710. // NOTE: role_it is NOT valid in this case
  711. LLGroupRoleData* grd = new LLGroupRoleData(role_id, role_data,
  712. 0);
  713. mRoles[role_id] = grd;
  714. need_role_data = true;
  715. break;
  716. }
  717. case RC_DELETE:
  718. {
  719. LLGroupRoleData* group_role_data = role_it->second;
  720. delete group_role_data;
  721. mRoles.erase(role_it);
  722. need_role_cleanup = true;
  723. need_power_recalc = true;
  724. break;
  725. }
  726. case RC_UPDATE_ALL:
  727. case RC_UPDATE_POWERS:
  728. need_power_recalc = true;
  729. case RC_UPDATE_DATA:
  730. default:
  731. {
  732. LLGroupRoleData* group_role_data = role_it->second;
  733. // NOTE: might modify mRoleChanges !
  734. group_role_data->setRoleData(role_data);
  735. }
  736. }
  737. // Update dataserver
  738. start_message = packRoleUpdateMessageBlock(gMessageSystemp, getID(),
  739. role_id, role_data,
  740. start_message);
  741. }
  742. if (!start_message)
  743. {
  744. gAgent.sendReliableMessage();
  745. }
  746. // If we delete a role then all the role-member pairs are invalid !
  747. if (need_role_cleanup)
  748. {
  749. removeRoleMemberData();
  750. }
  751. // If we create a new role, then we need to re-fetch all the role data.
  752. if (need_role_data)
  753. {
  754. gGroupMgr.sendGroupRoleDataRequest(getID());
  755. }
  756. // Clean up change lists
  757. mRoleChanges.clear();
  758. // Recalculate all the agent powers because role powers have now changed.
  759. if (need_power_recalc)
  760. {
  761. recalcAllAgentPowers();
  762. }
  763. }
  764. void LLGroupMgrGroupData::cancelRoleChanges()
  765. {
  766. // Clear out all changes !
  767. mRoleChanges.clear();
  768. }
  769. void LLGroupMgrGroupData::createBanEntry(const LLUUID& ban_id,
  770. const LLGroupBanData& ban_data)
  771. {
  772. mBanList[ban_id] = ban_data;
  773. }
  774. void LLGroupMgrGroupData::removeBanEntry(const LLUUID& ban_id)
  775. {
  776. mBanList.erase(ban_id);
  777. }
  778. //
  779. // LLGroupMgr
  780. //
  781. LLGroupMgr::LLGroupMgr()
  782. : mLastGroupMembersRequestTime(0.f),
  783. mMemberRequestInFlight(false)
  784. {
  785. }
  786. LLGroupMgr::~LLGroupMgr()
  787. {
  788. clearGroups();
  789. }
  790. void LLGroupMgr::clearGroups()
  791. {
  792. std::for_each(mRoleActionSets.begin(), mRoleActionSets.end(),
  793. DeletePointer());
  794. mRoleActionSets.clear();
  795. for (auto it = mGroups.begin(), end = mGroups.end(); it != end; ++it)
  796. {
  797. delete it->second;
  798. }
  799. mGroups.clear();
  800. mObservers.clear();
  801. }
  802. void LLGroupMgr::clearGroupData(const LLUUID& group_id)
  803. {
  804. group_map_t::iterator iter = mGroups.find(group_id);
  805. if (iter != mGroups.end())
  806. {
  807. delete iter->second;
  808. mGroups.hmap_erase(iter);
  809. }
  810. }
  811. void LLGroupMgr::addObserver(LLGroupMgrObserver* observerp)
  812. {
  813. if (observerp && observerp->getID().notNull())
  814. {
  815. mObservers.emplace(observerp->getID(), observerp);
  816. }
  817. }
  818. void LLGroupMgr::removeObserver(LLGroupMgrObserver* observer)
  819. {
  820. if (observer)
  821. {
  822. observer_multimap_t::iterator it;
  823. it = mObservers.find(observer->getID());
  824. while (it != mObservers.end())
  825. {
  826. if (it->second == observer)
  827. {
  828. mObservers.erase(it);
  829. break;
  830. }
  831. else
  832. {
  833. ++it;
  834. }
  835. }
  836. }
  837. }
  838. LLGroupMgrGroupData* LLGroupMgr::getGroupData(const LLUUID& id)
  839. {
  840. group_map_t::iterator gi = mGroups.find(id);
  841. return gi != mGroups.end() ? gi->second : NULL;
  842. }
  843. bool LLGroupMgr::agentCanAddToRole(const LLUUID& group_id,
  844. const LLUUID& role_id)
  845. {
  846. LLGroupMgrGroupData* gdatap = getGroupData(group_id);
  847. if (!gdatap)
  848. {
  849. llinfos << "No group data for group Id: " << group_id
  850. << " - Creating and fetching data now..." << llendl;
  851. fetchGroupMissingData(group_id);
  852. return false;
  853. }
  854. bool is_god = gAgent.isGodlikeWithoutAdminMenuFakery();
  855. // Make sure the agent is in the group
  856. LLGroupMgrGroupData::member_list_t::iterator mi =
  857. gdatap->mMembers.find(gAgentID);
  858. if (mi == gdatap->mMembers.end())
  859. {
  860. if (!gdatap->isMemberDataComplete())
  861. {
  862. llinfos << "No group member data received for group Id: "
  863. << group_id << " - Fetching data now..." << llendl;
  864. fetchGroupMissingData(group_id);
  865. }
  866. return is_god;
  867. }
  868. bool needs_data_fetch = false;
  869. if (gdatap->isGroupPropertiesDataComplete())
  870. {
  871. // 'assign members' can add to non-owner roles.
  872. if (gAgent.hasPowerInGroup(group_id, GP_ROLE_ASSIGN_MEMBER) &&
  873. role_id != gdatap->mOwnerRole)
  874. {
  875. return true;
  876. }
  877. }
  878. else
  879. {
  880. llinfos << "No group properties data received for group Id: "
  881. << group_id << llendl;
  882. needs_data_fetch = true;
  883. fetchGroupMissingData(group_id);
  884. }
  885. if (!gdatap->isRoleDataComplete())
  886. {
  887. llinfos << "No role data received for group Id: " << group_id
  888. << llendl;
  889. needs_data_fetch = true;
  890. }
  891. LLGroupMemberData* member_data = mi->second;
  892. if (!member_data)
  893. {
  894. llwarns << "No member data for a known member in group Id: "
  895. << group_id << llendl;
  896. needs_data_fetch = true;
  897. }
  898. if (needs_data_fetch)
  899. {
  900. llinfos << "Fetching data now..." << llendl;
  901. fetchGroupMissingData(group_id);
  902. }
  903. // Owners can add to any role.
  904. if (member_data && member_data->isInRole(gdatap->mOwnerRole))
  905. {
  906. return true;
  907. }
  908. // 'Limited assign members' can add to roles the user is in.
  909. if (gAgent.hasPowerInGroup(group_id, GP_ROLE_ASSIGN_MEMBER_LIMITED) &&
  910. member_data && member_data->isInRole(role_id))
  911. {
  912. return true;
  913. }
  914. return is_god;
  915. }
  916. //static
  917. void LLGroupMgr::processGroupMembersReply(LLMessageSystem* msg, void** data)
  918. {
  919. LLUUID agent_id;
  920. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
  921. if (agent_id != gAgentID)
  922. {
  923. llwarns << "Got group members reply for another agent !" << llendl;
  924. return;
  925. }
  926. LLUUID group_id;
  927. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id);
  928. LLUUID request_id;
  929. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_RequestID, request_id);
  930. LLGroupMgrGroupData* gdatap = gGroupMgr.getGroupData(group_id);
  931. #if 0
  932. if (!gdatap)
  933. {
  934. LL_DEBUGS("GroupMgr") << "Creating a new group data for group "
  935. << group_id
  936. << " during group member reply processing"
  937. << LL_ENDL;
  938. gdatap = gGroupMgr.createGroupData(group_id);
  939. }
  940. #endif
  941. if (!gdatap || gdatap->mMemberRequestID != request_id)
  942. {
  943. llwarns << "Received incorrect, possibly stale request Id" << llendl;
  944. return;
  945. }
  946. msg->getS32(_PREHASH_GroupData, "MemberCount", gdatap->mMemberCount);
  947. if (gdatap->mMemberCount > 0)
  948. {
  949. S32 contribution = 0;
  950. std::string online_status;
  951. std::string title;
  952. U64 agent_powers = 0;
  953. bool is_owner = false;
  954. S32 num_members = msg->getNumberOfBlocksFast(_PREHASH_MemberData);
  955. std::string date_format = gSavedSettings.getString("ShortDateFormat");
  956. for (S32 i = 0; i < num_members; ++i)
  957. {
  958. LLUUID member_id;
  959. msg->getUUIDFast(_PREHASH_MemberData, _PREHASH_AgentID, member_id,
  960. i);
  961. msg->getS32(_PREHASH_MemberData, _PREHASH_Contribution,
  962. contribution, i);
  963. msg->getU64(_PREHASH_MemberData, _PREHASH_AgentPowers,
  964. agent_powers, i);
  965. msg->getStringFast(_PREHASH_MemberData, _PREHASH_OnlineStatus,
  966. online_status, i);
  967. msg->getString(_PREHASH_MemberData, _PREHASH_Title, title, i);
  968. msg->getBool(_PREHASH_MemberData, _PREHASH_IsOwner, is_owner, i);
  969. if (member_id.notNull())
  970. {
  971. tm t;
  972. if (online_status != "Online" &&
  973. sscanf(online_status.c_str(), "%u/%u/%u", &t.tm_mon,
  974. &t.tm_mday, &t.tm_year) == 3 && t.tm_year > 1900)
  975. {
  976. t.tm_year -= 1900;
  977. t.tm_mon--;
  978. t.tm_hour = t.tm_min = t.tm_sec = 0;
  979. timeStructToFormattedString(&t, date_format, online_status);
  980. }
  981. LL_DEBUGS("GroupMgr") << "Member " << member_id
  982. << " has powers " << std::hex
  983. << agent_powers << std::dec << LL_ENDL;
  984. LLGroupMemberData* newdata =
  985. new LLGroupMemberData(member_id, contribution,
  986. agent_powers, title, online_status,
  987. is_owner);
  988. LLGroupMgrGroupData::member_list_t::iterator mit =
  989. gdatap->mMembers.find(member_id);
  990. if (mit != gdatap->mMembers.end())
  991. {
  992. LL_DEBUGS("GroupMgr") << "Received duplicate member data for agent "
  993. << member_id << LL_ENDL;
  994. }
  995. gdatap->mMembers[member_id] = newdata;
  996. }
  997. else
  998. {
  999. llinfos << "Received null group member data." << llendl;
  1000. }
  1001. }
  1002. // If group members are loaded while titles are missing, load the
  1003. // titles.
  1004. if (gdatap->mTitles.empty())
  1005. {
  1006. gGroupMgr.sendGroupTitlesRequest(group_id);
  1007. }
  1008. }
  1009. if (gdatap->mMembers.size() == (U32)gdatap->mMemberCount)
  1010. {
  1011. gdatap->mMemberDataComplete = true;
  1012. gdatap->mMemberRequestID.setNull();
  1013. // We do not want to make role-member data requests until we have all
  1014. // the members
  1015. if (gdatap->mPendingRoleMemberRequest)
  1016. {
  1017. gdatap->mPendingRoleMemberRequest = false;
  1018. gGroupMgr.sendGroupRoleMembersRequest(gdatap->mID);
  1019. }
  1020. }
  1021. gdatap->mChanged = true;
  1022. gGroupMgr.notifyObservers(GC_MEMBER_DATA);
  1023. }
  1024. //static
  1025. void LLGroupMgr::processGroupPropertiesReply(LLMessageSystem* msg, void** data)
  1026. {
  1027. LLUUID agent_id;
  1028. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
  1029. if (agent_id != gAgentID)
  1030. {
  1031. llwarns << "Got group properties reply for another agent !" << llendl;
  1032. return;
  1033. }
  1034. LLUUID group_id;
  1035. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id);
  1036. LLUUID founder_id;
  1037. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_FounderID, founder_id);
  1038. std::string name;
  1039. msg->getStringFast(_PREHASH_GroupData, _PREHASH_Name, name);
  1040. std::string charter;
  1041. msg->getStringFast(_PREHASH_GroupData, _PREHASH_Charter, charter);
  1042. bool show_in_list = false;
  1043. msg->getBoolFast(_PREHASH_GroupData, _PREHASH_ShowInList, show_in_list);
  1044. std::string member_title;
  1045. msg->getStringFast(_PREHASH_GroupData, _PREHASH_MemberTitle, member_title);
  1046. LLUUID insignia_id;
  1047. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_InsigniaID, insignia_id);
  1048. U64 powers_mask = GP_NO_POWERS;
  1049. msg->getU64Fast(_PREHASH_GroupData, _PREHASH_PowersMask, powers_mask);
  1050. U32 membership_fee = 0;
  1051. msg->getU32Fast(_PREHASH_GroupData, _PREHASH_MembershipFee,
  1052. membership_fee);
  1053. bool open_enrollment = false;
  1054. msg->getBoolFast(_PREHASH_GroupData, _PREHASH_OpenEnrollment,
  1055. open_enrollment);
  1056. S32 num_group_members = 0;
  1057. msg->getS32Fast(_PREHASH_GroupData, _PREHASH_GroupMembershipCount,
  1058. num_group_members);
  1059. S32 num_group_roles = 0;
  1060. msg->getS32(_PREHASH_GroupData, _PREHASH_GroupRolesCount, num_group_roles);
  1061. S32 money = 0;
  1062. msg->getS32Fast(_PREHASH_GroupData, _PREHASH_Money, money);
  1063. bool allow_publish = false;
  1064. msg->getBool(_PREHASH_GroupData, _PREHASH_AllowPublish, allow_publish);
  1065. bool mature = false;
  1066. msg->getBool(_PREHASH_GroupData, _PREHASH_MaturePublish, mature);
  1067. LLUUID owner_role;
  1068. msg->getUUID(_PREHASH_GroupData, _PREHASH_OwnerRole, owner_role);
  1069. LLGroupMgrGroupData* gdatap = gGroupMgr.createGroupData(group_id);
  1070. gdatap->mName = name;
  1071. gdatap->mCharter = charter;
  1072. gdatap->mShowInList = show_in_list;
  1073. gdatap->mInsigniaID = insignia_id;
  1074. gdatap->mFounderID = founder_id;
  1075. gdatap->mMembershipFee = membership_fee;
  1076. gdatap->mOpenEnrollment = open_enrollment;
  1077. gdatap->mAllowPublish = allow_publish;
  1078. gdatap->mMaturePublish = mature;
  1079. gdatap->mOwnerRole = owner_role;
  1080. gdatap->mMemberCount = num_group_members;
  1081. gdatap->mRoleCount = num_group_roles + 1; // Add the everyone role.
  1082. gdatap->mGroupPropertiesDataComplete = true;
  1083. gdatap->mChanged = true;
  1084. gGroupMgr.notifyObservers(GC_PROPERTIES);
  1085. }
  1086. //static
  1087. void LLGroupMgr::processGroupRoleDataReply(LLMessageSystem* msg, void** data)
  1088. {
  1089. LLUUID agent_id;
  1090. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
  1091. if (agent_id != gAgentID)
  1092. {
  1093. llwarns << "Got group roles reply for another agent !" << llendl;
  1094. return;
  1095. }
  1096. LLUUID group_id;
  1097. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id);
  1098. LLUUID request_id;
  1099. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_RequestID, request_id);
  1100. LLGroupMgrGroupData* gdatap = gGroupMgr.getGroupData(group_id);
  1101. #if 0
  1102. if (!gdatap)
  1103. {
  1104. LL_DEBUGS("GroupMgr") << "Creating a new group data for group "
  1105. << group_id
  1106. << " during group role reply processing"
  1107. << LL_ENDL;
  1108. gdatap = gGroupMgr.createGroupData(group_id);
  1109. }
  1110. #endif
  1111. if (!gdatap || gdatap->mRoleDataRequestID != request_id)
  1112. {
  1113. llwarns << "Received incorrect, possibly stale request Id" << llendl;
  1114. return;
  1115. }
  1116. msg->getS32(_PREHASH_GroupData, "RoleCount", gdatap->mRoleCount);
  1117. std::string name;
  1118. std::string title;
  1119. std::string desc;
  1120. U64 powers = 0;
  1121. U32 member_count = 0;
  1122. LLUUID role_id;
  1123. U32 num_blocks = msg->getNumberOfBlocks(_PREHASH_RoleData);
  1124. U32 i = 0;
  1125. for (i = 0; i < num_blocks; ++i)
  1126. {
  1127. msg->getUUID(_PREHASH_RoleData, _PREHASH_RoleID, role_id, i);
  1128. msg->getString(_PREHASH_RoleData, _PREHASH_Name, name, i);
  1129. msg->getString(_PREHASH_RoleData, _PREHASH_Title, title, i);
  1130. msg->getString(_PREHASH_RoleData, _PREHASH_Description, desc, i);
  1131. msg->getU64(_PREHASH_RoleData, _PREHASH_Powers, powers, i);
  1132. msg->getU32(_PREHASH_RoleData, _PREHASH_Members, member_count, i);
  1133. LL_DEBUGS("GroupMgr") << "Adding role data: " << name << " {"
  1134. << role_id << "}" << LL_ENDL;
  1135. LLGroupRoleData* rd = new LLGroupRoleData(role_id, name, title, desc,
  1136. powers, member_count);
  1137. gdatap->mRoles[role_id] = rd;
  1138. }
  1139. if (gdatap->mRoles.size() == (U32)gdatap->mRoleCount)
  1140. {
  1141. gdatap->mRoleDataComplete = true;
  1142. gdatap->mRoleDataRequestID.setNull();
  1143. // We do not want to make role-member data requests until we have all
  1144. // the role data
  1145. if (gdatap->mPendingRoleMemberRequest)
  1146. {
  1147. gdatap->mPendingRoleMemberRequest = false;
  1148. gGroupMgr.sendGroupRoleMembersRequest(gdatap->mID);
  1149. }
  1150. }
  1151. gdatap->mChanged = true;
  1152. gGroupMgr.notifyObservers(GC_ROLE_DATA);
  1153. }
  1154. //static
  1155. void LLGroupMgr::processGroupRoleMembersReply(LLMessageSystem* msg, void** data)
  1156. {
  1157. LLUUID agent_id;
  1158. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
  1159. if (agent_id != gAgentID)
  1160. {
  1161. llwarns << "Got group role members reply for another agent !"
  1162. << llendl;
  1163. return;
  1164. }
  1165. LLUUID request_id;
  1166. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_RequestID, request_id);
  1167. LLUUID group_id;
  1168. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_GroupID, group_id);
  1169. U32 total_pairs;
  1170. msg->getU32(_PREHASH_AgentData, _PREHASH_TotalPairs, total_pairs);
  1171. LLGroupMgrGroupData* gdatap = gGroupMgr.getGroupData(group_id);
  1172. #if 0
  1173. if (!gdatap)
  1174. {
  1175. LL_DEBUGS("GroupMgr") << "Creating a new group data for group "
  1176. << group_id
  1177. << " during role member reply processing"
  1178. << LL_ENDL;
  1179. gdatap = gGroupMgr.createGroupData(group_id);
  1180. }
  1181. #endif
  1182. if (!gdatap || gdatap->mRoleMembersRequestID != request_id)
  1183. {
  1184. llwarns << "Received incorrect, possibly stale request Id" << llendl;
  1185. return;
  1186. }
  1187. U32 num_blocks = msg->getNumberOfBlocks(_PREHASH_MemberData);
  1188. U32 i;
  1189. LLUUID member_id;
  1190. LLUUID role_id;
  1191. LLGroupRoleData* rd = NULL;
  1192. LLGroupMemberData* md = NULL;
  1193. LLGroupMgrGroupData::role_list_t::iterator ri;
  1194. LLGroupMgrGroupData::member_list_t::iterator mi;
  1195. // If total_pairs == 0, there are no members in any custom roles.
  1196. if (total_pairs > 0)
  1197. {
  1198. for (i = 0;i < num_blocks; ++i)
  1199. {
  1200. msg->getUUID(_PREHASH_MemberData, _PREHASH_RoleID, role_id, i);
  1201. msg->getUUID(_PREHASH_MemberData, _PREHASH_MemberID, member_id, i);
  1202. if (role_id.notNull() && member_id.notNull())
  1203. {
  1204. rd = NULL;
  1205. ri = gdatap->mRoles.find(role_id);
  1206. if (ri != gdatap->mRoles.end())
  1207. {
  1208. rd = ri->second;
  1209. }
  1210. md = NULL;
  1211. mi = gdatap->mMembers.find(member_id);
  1212. if (mi != gdatap->mMembers.end())
  1213. {
  1214. md = mi->second;
  1215. }
  1216. if (rd && md)
  1217. {
  1218. LL_DEBUGS("GroupMgr") << "Adding role-member pair: "
  1219. << role_id << ", " << member_id
  1220. << LL_ENDL;
  1221. rd->addMember(member_id);
  1222. md->addRole(role_id, rd);
  1223. }
  1224. else
  1225. {
  1226. if (!rd)
  1227. {
  1228. llwarns << "Received role data for unkown role "
  1229. << role_id << " in group " << group_id
  1230. << llendl;
  1231. }
  1232. if (!md)
  1233. {
  1234. llwarns << "Received role data for unkown member "
  1235. << member_id << " in group " << group_id
  1236. << llendl;
  1237. }
  1238. }
  1239. }
  1240. }
  1241. gdatap->mReceivedRoleMemberPairs += num_blocks;
  1242. }
  1243. if (gdatap->mReceivedRoleMemberPairs == total_pairs)
  1244. {
  1245. // Add role data for the 'everyone' role to all members
  1246. LLGroupRoleData* everyone = gdatap->mRoles[LLUUID::null];
  1247. if (!everyone)
  1248. {
  1249. llwarns << "Everyone role not found !" << llendl;
  1250. }
  1251. else
  1252. {
  1253. for (LLGroupMgrGroupData::member_list_t::iterator
  1254. mi = gdatap->mMembers.begin(),
  1255. end = gdatap->mMembers.end();
  1256. mi != end; ++mi)
  1257. {
  1258. LLGroupMemberData* data = mi->second;
  1259. if (data)
  1260. {
  1261. data->addRole(LLUUID::null,everyone);
  1262. }
  1263. }
  1264. }
  1265. gdatap->mRoleMemberDataComplete = true;
  1266. gdatap->mRoleMembersRequestID.setNull();
  1267. }
  1268. gdatap->mChanged = true;
  1269. gGroupMgr.notifyObservers(GC_ROLE_MEMBER_DATA);
  1270. }
  1271. //static
  1272. void LLGroupMgr::processGroupTitlesReply(LLMessageSystem* msg, void** data)
  1273. {
  1274. LLUUID agent_id;
  1275. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
  1276. if (agent_id != gAgentID)
  1277. {
  1278. llwarns << "Got group titles reply for another agent !" << llendl;
  1279. return;
  1280. }
  1281. LLUUID group_id;
  1282. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_GroupID, group_id);
  1283. LLUUID request_id;
  1284. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_RequestID, request_id);
  1285. LLGroupMgrGroupData* gdatap = gGroupMgr.getGroupData(group_id);
  1286. #if 0
  1287. if (!gdatap)
  1288. {
  1289. LL_DEBUGS("GroupMgr") << "Creating a new group data for group "
  1290. << group_id
  1291. << " during group titles reply processing"
  1292. << LL_ENDL;
  1293. gdatap = gGroupMgr.createGroupData(group_id);
  1294. }
  1295. #endif
  1296. if (!gdatap || gdatap->mTitlesRequestID != request_id)
  1297. {
  1298. llwarns << "Received incorrect, possibly stale request Id" << llendl;
  1299. return;
  1300. }
  1301. LLGroupTitle title;
  1302. S32 blocks = msg->getNumberOfBlocksFast(_PREHASH_GroupData);
  1303. for (S32 i = 0; i < blocks; ++i)
  1304. {
  1305. msg->getString(_PREHASH_GroupData, _PREHASH_Title, title.mTitle, i);
  1306. msg->getUUID(_PREHASH_GroupData, _PREHASH_RoleID, title.mRoleID, i);
  1307. msg->getBool(_PREHASH_GroupData, _PREHASH_Selected, title.mSelected,
  1308. i);
  1309. if (!title.mTitle.empty())
  1310. {
  1311. LL_DEBUGS("GroupMgr") << "LLGroupMgr adding title: "
  1312. << title.mTitle << ", " << title.mRoleID
  1313. << ", " << (title.mSelected ? 'Y' : 'N')
  1314. << LL_ENDL;
  1315. gdatap->mTitles.emplace_back(title);
  1316. }
  1317. }
  1318. gdatap->mChanged = true;
  1319. gGroupMgr.notifyObservers(GC_TITLES);
  1320. }
  1321. //static
  1322. void LLGroupMgr::processEjectGroupMemberReply(LLMessageSystem* msg, void ** data)
  1323. {
  1324. LLUUID group_id;
  1325. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id);
  1326. bool success;
  1327. msg->getBoolFast(_PREHASH_EjectData, _PREHASH_Success, success);
  1328. // If we had a failure, the group panel needs to be updated.
  1329. if (!success)
  1330. {
  1331. LLFloaterGroupInfo::refreshGroup(group_id);
  1332. }
  1333. }
  1334. //static
  1335. void LLGroupMgr::processJoinGroupReply(LLMessageSystem* msg, void** data)
  1336. {
  1337. LLUUID group_id;
  1338. bool success;
  1339. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id);
  1340. msg->getBoolFast(_PREHASH_GroupData, _PREHASH_Success, success);
  1341. if (success)
  1342. {
  1343. // Refresh all group information
  1344. gAgent.sendAgentDataUpdateRequest();
  1345. gGroupMgr.clearGroupData(group_id);
  1346. // Refresh the floater for this group, if any.
  1347. LLFloaterGroupInfo::refreshGroup(group_id);
  1348. // Refresh the group panel of the search window, if necessary.
  1349. HBFloaterSearch::refreshGroup(group_id);
  1350. }
  1351. }
  1352. //static
  1353. void LLGroupMgr::processLeaveGroupReply(LLMessageSystem* msg, void** data)
  1354. {
  1355. LLUUID group_id;
  1356. bool success;
  1357. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id);
  1358. msg->getBoolFast(_PREHASH_GroupData, _PREHASH_Success, success);
  1359. if (success)
  1360. {
  1361. // Refresh all group information
  1362. gAgent.sendAgentDataUpdateRequest();
  1363. gGroupMgr.clearGroupData(group_id);
  1364. // close the floater for this group, if any.
  1365. LLFloaterGroupInfo::closeGroup(group_id);
  1366. // Refresh the group panel of the search window, if necessary.
  1367. HBFloaterSearch::refreshGroup(group_id);
  1368. }
  1369. }
  1370. //static
  1371. void LLGroupMgr::processCreateGroupReply(LLMessageSystem* msg, void ** data)
  1372. {
  1373. LLUUID group_id;
  1374. msg->getUUIDFast(_PREHASH_ReplyData, _PREHASH_GroupID, group_id);
  1375. bool success;
  1376. msg->getBoolFast(_PREHASH_ReplyData, _PREHASH_Success, success);
  1377. std::string message;
  1378. msg->getStringFast(_PREHASH_ReplyData, _PREHASH_Message, message);
  1379. if (success)
  1380. {
  1381. // Refresh all group information
  1382. gAgent.sendAgentDataUpdateRequest();
  1383. // *HACK: we have not gotten the agent group update yet, so fake it.
  1384. // This is so when we go to modify the group we will be able to do so.
  1385. // This is not actually too bad because real data will come down in 2
  1386. // or 3 miliseconds and replace this.
  1387. gAgent.mGroups.emplace_back(group_id, "new group", GP_ALL_POWERS);
  1388. LLFloaterGroupInfo::closeCreateGroup();
  1389. LLFloaterGroupInfo::showFromUUID(group_id,"roles_tab");
  1390. }
  1391. else
  1392. {
  1393. // *TODO:translate
  1394. LLSD args;
  1395. args["MESSAGE"] = message;
  1396. gNotifications.add("UnableToCreateGroup", args);
  1397. }
  1398. }
  1399. LLGroupMgrGroupData* LLGroupMgr::createGroupData(const LLUUID& id)
  1400. {
  1401. LLGroupMgrGroupData* gdatap = NULL;
  1402. group_map_t::iterator existing_group = mGroups.find(id);
  1403. if (existing_group == mGroups.end())
  1404. {
  1405. gdatap = new LLGroupMgrGroupData(id);
  1406. addGroup(gdatap);
  1407. }
  1408. else
  1409. {
  1410. gdatap = existing_group->second;
  1411. }
  1412. if (gdatap)
  1413. {
  1414. gdatap->setAccessed();
  1415. }
  1416. return gdatap;
  1417. }
  1418. void LLGroupMgr::notifyObservers(LLGroupChange gc)
  1419. {
  1420. for (group_map_t::iterator gi = mGroups.begin(), end = mGroups.end();
  1421. gi != end; ++gi)
  1422. {
  1423. LLUUID group_id = gi->first;
  1424. if (gi->second->mChanged)
  1425. {
  1426. // Copy the map because observers may remove themselves on update
  1427. observer_multimap_t observers = mObservers;
  1428. // Find all observers for this group id
  1429. for (observer_multimap_t::iterator
  1430. oi = observers.lower_bound(group_id),
  1431. end2 = observers.upper_bound(group_id);
  1432. oi != end2; ++oi)
  1433. {
  1434. oi->second->changed(gc);
  1435. }
  1436. gi->second->mChanged = false;
  1437. }
  1438. }
  1439. }
  1440. void LLGroupMgr::addGroup(LLGroupMgrGroupData* gdatap)
  1441. {
  1442. while (mGroups.size() >= MAX_CACHED_GROUPS)
  1443. {
  1444. // LRU: Remove the oldest un-observed group from cache until group size
  1445. // is small enough
  1446. F32 oldest_access = LLFrameTimer::getTotalSeconds();
  1447. group_map_t::iterator oldest_gi = mGroups.end();
  1448. for (group_map_t::iterator gi = mGroups.begin(); gi != mGroups.end();
  1449. ++gi)
  1450. {
  1451. observer_multimap_t::iterator oi = mObservers.find(gi->first);
  1452. if (oi == mObservers.end())
  1453. {
  1454. if (gi->second && gi->second->getAccessTime() < oldest_access)
  1455. {
  1456. oldest_access = gi->second->getAccessTime();
  1457. oldest_gi = gi;
  1458. }
  1459. }
  1460. }
  1461. if (oldest_gi != mGroups.end())
  1462. {
  1463. delete oldest_gi->second;
  1464. mGroups.erase(oldest_gi);
  1465. }
  1466. else
  1467. {
  1468. // All groups must be currently open, none to remove.
  1469. // Just add the new group anyway, but get out of this loop as it
  1470. // will never drop below max_cached_groups.
  1471. break;
  1472. }
  1473. }
  1474. mGroups[gdatap->getID()] = gdatap;
  1475. }
  1476. bool LLGroupMgr::fetchGroupMissingData(const LLUUID& group_id)
  1477. {
  1478. if (!gAgent.isInGroup(group_id))
  1479. {
  1480. return false;
  1481. }
  1482. bool fetching = false;
  1483. // Start requesting member and role data if needed.
  1484. LLGroupMgrGroupData* gdatap = getGroupData(group_id);
  1485. // Check member data.
  1486. if (!gdatap || !gdatap->isMemberDataComplete())
  1487. {
  1488. sendCapGroupMembersRequest(group_id);
  1489. fetching = true;
  1490. }
  1491. // Check role data.
  1492. if (!gdatap || !gdatap->isRoleDataComplete())
  1493. {
  1494. sendGroupRoleDataRequest(group_id);
  1495. fetching = true;
  1496. }
  1497. // Check role-member mapping data.
  1498. if (!gdatap || !gdatap->isRoleMemberDataComplete())
  1499. {
  1500. sendGroupRoleMembersRequest(group_id);
  1501. fetching = true;
  1502. }
  1503. // Check group titles data.
  1504. if (!gdatap || !gdatap->isGroupTitlePending())
  1505. {
  1506. sendGroupTitlesRequest(group_id);
  1507. fetching = true;
  1508. }
  1509. // Need this to get base group member powers
  1510. if (!gdatap || !gdatap->isGroupPropertiesDataComplete())
  1511. {
  1512. sendGroupPropertiesRequest(group_id);
  1513. fetching = true;
  1514. }
  1515. return fetching;
  1516. }
  1517. void LLGroupMgr::sendGroupPropertiesRequest(const LLUUID& group_id)
  1518. {
  1519. #if 0 // This will happen when we get the reply
  1520. LLGroupMgrGroupData* gdatap = createGroupData(group_id);
  1521. #endif
  1522. LLMessageSystem* msg = gMessageSystemp;
  1523. msg->newMessage(_PREHASH_GroupProfileRequest);
  1524. msg->nextBlock(_PREHASH_AgentData);
  1525. msg->addUUID(_PREHASH_AgentID, gAgentID);
  1526. msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
  1527. msg->nextBlock(_PREHASH_GroupData);
  1528. msg->addUUID(_PREHASH_GroupID, group_id);
  1529. gAgent.sendReliableMessage();
  1530. }
  1531. void LLGroupMgr::sendGroupMembersRequest(const LLUUID& group_id)
  1532. {
  1533. LLGroupMgrGroupData* gdatap = createGroupData(group_id);
  1534. if (gdatap && gdatap->mMemberRequestID.isNull())
  1535. {
  1536. gdatap->removeMemberData();
  1537. gdatap->mMemberRequestID.generate();
  1538. LLMessageSystem* msg = gMessageSystemp;
  1539. msg->newMessage(_PREHASH_GroupMembersRequest);
  1540. msg->nextBlock(_PREHASH_AgentData);
  1541. msg->addUUID(_PREHASH_AgentID, gAgentID);
  1542. msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
  1543. msg->nextBlock(_PREHASH_GroupData);
  1544. msg->addUUID(_PREHASH_GroupID, group_id);
  1545. msg->addUUID(_PREHASH_RequestID, gdatap->mMemberRequestID);
  1546. gAgent.sendReliableMessage();
  1547. }
  1548. }
  1549. void LLGroupMgr::sendGroupRoleDataRequest(const LLUUID& group_id)
  1550. {
  1551. LLGroupMgrGroupData* gdatap = createGroupData(group_id);
  1552. if (gdatap && gdatap->mRoleDataRequestID.isNull())
  1553. {
  1554. gdatap->removeRoleData();
  1555. gdatap->mRoleDataRequestID.generate();
  1556. LLMessageSystem* msg = gMessageSystemp;
  1557. msg->newMessage(_PREHASH_GroupRoleDataRequest);
  1558. msg->nextBlock(_PREHASH_AgentData);
  1559. msg->addUUID(_PREHASH_AgentID, gAgentID);
  1560. msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
  1561. msg->nextBlock(_PREHASH_GroupData);
  1562. msg->addUUID(_PREHASH_GroupID, group_id);
  1563. msg->addUUID(_PREHASH_RequestID, gdatap->mRoleDataRequestID);
  1564. gAgent.sendReliableMessage();
  1565. }
  1566. }
  1567. void LLGroupMgr::sendGroupRoleMembersRequest(const LLUUID& group_id)
  1568. {
  1569. LLGroupMgrGroupData* gdatap = createGroupData(group_id);
  1570. if (gdatap && gdatap->mRoleMembersRequestID.isNull())
  1571. {
  1572. // Do not send the request if we do not have all the member or role
  1573. // data
  1574. if (!gdatap->isMemberDataComplete() ||
  1575. !gdatap->isRoleDataComplete())
  1576. {
  1577. // *FIXME: Should we start a member or role data request ?
  1578. llinfos << " Pending: "
  1579. << (gdatap->mPendingRoleMemberRequest ? "Y" : "N")
  1580. << " MemberDataComplete: "
  1581. << (gdatap->mMemberDataComplete ? "Y" : "N")
  1582. << " RoleDataComplete: "
  1583. << (gdatap->mRoleDataComplete ? "Y" : "N") << llendl;
  1584. gdatap->mPendingRoleMemberRequest = true;
  1585. return;
  1586. }
  1587. gdatap->removeRoleMemberData();
  1588. gdatap->mRoleMembersRequestID.generate();
  1589. LLMessageSystem* msg = gMessageSystemp;
  1590. msg->newMessage(_PREHASH_GroupRoleMembersRequest);
  1591. msg->nextBlock(_PREHASH_AgentData);
  1592. msg->addUUID(_PREHASH_AgentID, gAgentID);
  1593. msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
  1594. msg->nextBlock(_PREHASH_GroupData);
  1595. msg->addUUID(_PREHASH_GroupID, group_id);
  1596. msg->addUUID(_PREHASH_RequestID, gdatap->mRoleMembersRequestID);
  1597. gAgent.sendReliableMessage();
  1598. }
  1599. }
  1600. void LLGroupMgr::sendGroupTitlesRequest(const LLUUID& group_id)
  1601. {
  1602. LLGroupMgrGroupData* gdatap = createGroupData(group_id);
  1603. if (!gdatap) return;
  1604. gdatap->mTitles.clear();
  1605. gdatap->mTitlesRequestID.generate();
  1606. LLMessageSystem* msg = gMessageSystemp;
  1607. msg->newMessage(_PREHASH_GroupTitlesRequest);
  1608. msg->nextBlock(_PREHASH_AgentData);
  1609. msg->addUUID(_PREHASH_AgentID, gAgentID);
  1610. msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
  1611. msg->addUUID(_PREHASH_GroupID, group_id);
  1612. msg->addUUID(_PREHASH_RequestID, gdatap->mTitlesRequestID);
  1613. gAgent.sendReliableMessage();
  1614. }
  1615. void LLGroupMgr::sendGroupTitleUpdate(const LLUUID& group_id,
  1616. const LLUUID& title_role_id)
  1617. {
  1618. LLMessageSystem* msg = gMessageSystemp;
  1619. msg->newMessage(_PREHASH_GroupTitleUpdate);
  1620. msg->nextBlock(_PREHASH_AgentData);
  1621. msg->addUUID(_PREHASH_AgentID, gAgentID);
  1622. msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
  1623. msg->addUUID(_PREHASH_GroupID, group_id);
  1624. msg->addUUID(_PREHASH_TitleRoleID, title_role_id);
  1625. gAgent.sendReliableMessage();
  1626. // Save the change locally
  1627. LLGroupMgrGroupData* gdatap = createGroupData(group_id);
  1628. for (std::vector<LLGroupTitle>::iterator iter = gdatap->mTitles.begin(),
  1629. end = gdatap->mTitles.end();
  1630. iter != end; ++iter)
  1631. {
  1632. if (iter->mRoleID == title_role_id)
  1633. {
  1634. iter->mSelected = true;
  1635. }
  1636. else if (iter->mSelected)
  1637. {
  1638. iter->mSelected = false;
  1639. }
  1640. }
  1641. }
  1642. //static
  1643. void LLGroupMgr::sendCreateGroupRequest(const std::string& name,
  1644. const std::string& charter,
  1645. U8 show_in_list,
  1646. const LLUUID& insignia,
  1647. S32 membership_fee,
  1648. bool open_enrollment,
  1649. bool allow_publish,
  1650. bool mature_publish)
  1651. {
  1652. LLMessageSystem* msg = gMessageSystemp;
  1653. msg->newMessage(_PREHASH_CreateGroupRequest);
  1654. msg->nextBlock(_PREHASH_AgentData);
  1655. msg->addUUID(_PREHASH_AgentID, gAgentID);
  1656. msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
  1657. msg->nextBlock(_PREHASH_GroupData);
  1658. msg->addString(_PREHASH_Name, name);
  1659. msg->addString(_PREHASH_Charter, charter);
  1660. msg->addBool(_PREHASH_ShowInList, show_in_list);
  1661. msg->addUUID(_PREHASH_InsigniaID, insignia);
  1662. msg->addS32(_PREHASH_MembershipFee, membership_fee);
  1663. msg->addBool(_PREHASH_OpenEnrollment, open_enrollment);
  1664. msg->addBool(_PREHASH_AllowPublish, allow_publish);
  1665. msg->addBool(_PREHASH_MaturePublish, mature_publish);
  1666. gAgent.sendReliableMessage();
  1667. }
  1668. void LLGroupMgr::sendUpdateGroupInfo(const LLUUID& group_id)
  1669. {
  1670. LLGroupMgrGroupData* gdatap = createGroupData(group_id);
  1671. if (!gdatap) return;
  1672. LLMessageSystem* msg = gMessageSystemp;
  1673. msg->newMessageFast(_PREHASH_UpdateGroupInfo);
  1674. msg->nextBlockFast(_PREHASH_AgentData);
  1675. msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
  1676. msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
  1677. msg->nextBlockFast(_PREHASH_GroupData);
  1678. msg->addUUIDFast(_PREHASH_GroupID, gdatap->getID());
  1679. msg->addStringFast(_PREHASH_Charter, gdatap->mCharter);
  1680. msg->addBoolFast(_PREHASH_ShowInList, gdatap->mShowInList);
  1681. msg->addUUIDFast(_PREHASH_InsigniaID, gdatap->mInsigniaID);
  1682. msg->addS32Fast(_PREHASH_MembershipFee, gdatap->mMembershipFee);
  1683. msg->addBoolFast(_PREHASH_OpenEnrollment, gdatap->mOpenEnrollment);
  1684. msg->addBoolFast(_PREHASH_AllowPublish, gdatap->mAllowPublish);
  1685. msg->addBoolFast(_PREHASH_MaturePublish, gdatap->mMaturePublish);
  1686. gAgent.sendReliableMessage();
  1687. // Not expecting a response, so let anyone else watching know the data has
  1688. // changed.
  1689. gdatap->mChanged = true;
  1690. notifyObservers(GC_PROPERTIES);
  1691. }
  1692. void LLGroupMgr::sendGroupRoleMemberChanges(const LLUUID& group_id)
  1693. {
  1694. LLGroupMgrGroupData* gdatap = createGroupData(group_id);
  1695. if (!gdatap || gdatap->mRoleMemberChanges.empty()) return;
  1696. LLMessageSystem* msg = gMessageSystemp;
  1697. bool start_message = true;
  1698. for (LLGroupMgrGroupData::change_map_t::const_iterator
  1699. citer = gdatap->mRoleMemberChanges.begin(),
  1700. end = gdatap->mRoleMemberChanges.end();
  1701. citer != end; ++citer)
  1702. {
  1703. if (start_message)
  1704. {
  1705. msg->newMessage(_PREHASH_GroupRoleChanges);
  1706. msg->nextBlockFast(_PREHASH_AgentData);
  1707. msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
  1708. msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
  1709. msg->addUUIDFast(_PREHASH_GroupID, group_id);
  1710. start_message = false;
  1711. }
  1712. msg->nextBlock(_PREHASH_RoleChange);
  1713. msg->addUUID(_PREHASH_RoleID, citer->second.mRole);
  1714. msg->addUUID(_PREHASH_MemberID, citer->second.mMember);
  1715. msg->addU32(_PREHASH_Change, (U32)citer->second.mChange);
  1716. if (msg->isSendFullFast())
  1717. {
  1718. gAgent.sendReliableMessage();
  1719. start_message = true;
  1720. }
  1721. }
  1722. if (!start_message)
  1723. {
  1724. gAgent.sendReliableMessage();
  1725. }
  1726. gdatap->mRoleMemberChanges.clear();
  1727. // Not expecting a response, so let anyone else watching know the data has
  1728. // changed.
  1729. gdatap->mChanged = true;
  1730. notifyObservers(GC_ROLE_MEMBER_DATA);
  1731. }
  1732. //static
  1733. void LLGroupMgr::sendGroupMemberJoin(const LLUUID& group_id)
  1734. {
  1735. LLMessageSystem* msg = gMessageSystemp;
  1736. msg->newMessageFast(_PREHASH_JoinGroupRequest);
  1737. msg->nextBlockFast(_PREHASH_AgentData);
  1738. msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
  1739. msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
  1740. msg->nextBlockFast(_PREHASH_GroupData);
  1741. msg->addUUIDFast(_PREHASH_GroupID, group_id);
  1742. gAgent.sendReliableMessage();
  1743. }
  1744. // member_role_pairs is <member_id,role_id>
  1745. //static
  1746. void LLGroupMgr::sendGroupMemberInvites(const LLUUID& group_id,
  1747. role_member_pairs_t& member_role_pairs)
  1748. {
  1749. LLMessageSystem* msg = gMessageSystemp;
  1750. bool start_message = true;
  1751. for (role_member_pairs_t::iterator it = member_role_pairs.begin(),
  1752. end = member_role_pairs.end();
  1753. it != end; ++it)
  1754. {
  1755. if (start_message)
  1756. {
  1757. msg->newMessage(_PREHASH_InviteGroupRequest);
  1758. msg->nextBlock(_PREHASH_AgentData);
  1759. msg->addUUID(_PREHASH_AgentID, gAgentID);
  1760. msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
  1761. msg->nextBlock(_PREHASH_GroupData);
  1762. msg->addUUID(_PREHASH_GroupID, group_id);
  1763. start_message = false;
  1764. }
  1765. msg->nextBlock(_PREHASH_InviteData);
  1766. msg->addUUID(_PREHASH_InviteeID, it->first);
  1767. msg->addUUID(_PREHASH_RoleID, it->second);
  1768. if (msg->isSendFull())
  1769. {
  1770. gAgent.sendReliableMessage();
  1771. start_message = true;
  1772. }
  1773. }
  1774. if (!start_message)
  1775. {
  1776. gAgent.sendReliableMessage();
  1777. }
  1778. }
  1779. //static
  1780. void LLGroupMgr::sendGroupMemberEjects(const LLUUID& group_id,
  1781. uuid_vec_t& member_ids)
  1782. {
  1783. bool start_message = true;
  1784. LLGroupMgrGroupData* gdatap = gGroupMgr.getGroupData(group_id);
  1785. if (!gdatap) return;
  1786. LLMessageSystem* msg = gMessageSystemp;
  1787. for (uuid_vec_t::iterator it = member_ids.begin(), end = member_ids.end();
  1788. it != end; ++it)
  1789. {
  1790. // Can't use 'eject' to leave a group.
  1791. if (*it == gAgentID) continue;
  1792. // Make sure they are in the group, and we need the member data
  1793. LLGroupMgrGroupData::member_list_t::iterator mit = gdatap->mMembers.find(*it);
  1794. if (mit != gdatap->mMembers.end())
  1795. {
  1796. // Add them to the message
  1797. if (start_message)
  1798. {
  1799. msg->newMessage(_PREHASH_EjectGroupMemberRequest);
  1800. msg->nextBlock(_PREHASH_AgentData);
  1801. msg->addUUID(_PREHASH_AgentID, gAgentID);
  1802. msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
  1803. msg->nextBlock(_PREHASH_GroupData);
  1804. msg->addUUID(_PREHASH_GroupID, group_id);
  1805. start_message = false;
  1806. }
  1807. msg->nextBlock(_PREHASH_EjectData);
  1808. msg->addUUID(_PREHASH_EjecteeID, *it);
  1809. if (msg->isSendFull())
  1810. {
  1811. gAgent.sendReliableMessage();
  1812. start_message = true;
  1813. }
  1814. // Clean up groupmgr
  1815. for (LLGroupMemberData::role_list_t::iterator
  1816. rit = mit->second->roleBegin(),
  1817. rend = mit->second->roleEnd();
  1818. rit != rend; ++rit)
  1819. {
  1820. if (rit->first.notNull())
  1821. {
  1822. rit->second->removeMember(*it);
  1823. }
  1824. }
  1825. delete mit->second;
  1826. gdatap->mMembers.erase(*it);
  1827. }
  1828. }
  1829. if (!start_message)
  1830. {
  1831. gAgent.sendReliableMessage();
  1832. }
  1833. }
  1834. //static
  1835. void LLGroupMgr::getGroupBanRequestCoro(const std::string& url,
  1836. const LLUUID& group_id)
  1837. {
  1838. std::string final_url = url + "?group_id=" + group_id.asString();
  1839. LLCoreHttpUtil::HttpCoroutineAdapter adapter("groupMembersRequest");
  1840. LLSD result = adapter.getAndSuspend(final_url);
  1841. LLCore::HttpStatus status =
  1842. LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(result);
  1843. if (!status)
  1844. {
  1845. llwarns << "Error receiving group member data: " << status.toString()
  1846. << llendl;
  1847. }
  1848. else if (result.has("ban_list"))
  1849. {
  1850. result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
  1851. // group ban data received
  1852. processGroupBanRequest(result);
  1853. }
  1854. }
  1855. //static
  1856. void LLGroupMgr::postGroupBanRequestCoro(std::string url, LLUUID group_id,
  1857. U32 action,
  1858. const uuid_vec_t& ban_list,
  1859. bool update)
  1860. {
  1861. std::string final_url = url + "?group_id=" + group_id.asString();
  1862. LLSD body = LLSD::emptyMap();
  1863. body["ban_action"] = (LLSD::Integer)action;
  1864. // Add our list of potential banned residents to the list
  1865. body["ban_ids"] = LLSD::emptyArray();
  1866. LLSD ban_entry;
  1867. for (uuid_vec_t::const_iterator it = ban_list.begin(),
  1868. end = ban_list.end();
  1869. it != end; ++it)
  1870. {
  1871. ban_entry = *it;
  1872. body["ban_ids"].append(ban_entry);
  1873. }
  1874. LL_DEBUGS("GroupMgr") << "Posting data: " << body << LL_ENDL;
  1875. LLCore::HttpHeaders::ptr_t headers(new LLCore::HttpHeaders);
  1876. headers->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
  1877. LLCore::HttpOptions::ptr_t options(new LLCore::HttpOptions);
  1878. options->setFollowRedirects(false);
  1879. LLCoreHttpUtil::HttpCoroutineAdapter adapter("groupMembersRequest");
  1880. LLSD result = adapter.postAndSuspend(final_url, body, options, headers);
  1881. LLCore::HttpStatus status =
  1882. LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(result);
  1883. if (!status)
  1884. {
  1885. llwarns << "Error posting group member data: " << status.toString()
  1886. << llendl;
  1887. return;
  1888. }
  1889. if (result.has("ban_list"))
  1890. {
  1891. result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
  1892. // group ban data received
  1893. processGroupBanRequest(result);
  1894. }
  1895. if (update)
  1896. {
  1897. getGroupBanRequestCoro(url, group_id);
  1898. }
  1899. }
  1900. //static
  1901. void LLGroupMgr::sendGroupBanRequest(EBanRequestType request_type,
  1902. const LLUUID& group_id, U32 ban_action,
  1903. const uuid_vec_t& ban_list)
  1904. {
  1905. // Get our capability
  1906. const std::string& cap_url = gAgent.getRegionCapability("GroupAPIv1");
  1907. if (cap_url.empty())
  1908. {
  1909. return;
  1910. }
  1911. U32 action = ban_action & ~BAN_UPDATE;
  1912. bool update = (ban_action & BAN_UPDATE) == BAN_UPDATE;
  1913. switch (request_type)
  1914. {
  1915. case REQUEST_GET:
  1916. gCoros.launch("LLGroupMgr::getGroupBanRequestCoro",
  1917. boost::bind(&LLGroupMgr::getGroupBanRequestCoro,
  1918. cap_url, group_id));
  1919. break;
  1920. case REQUEST_POST:
  1921. gCoros.launch("LLGroupMgr::postGroupBanRequestCoro",
  1922. boost::bind(&LLGroupMgr::postGroupBanRequestCoro,
  1923. cap_url, group_id, action, ban_list,
  1924. update));
  1925. break;
  1926. default:
  1927. break;
  1928. }
  1929. }
  1930. //static
  1931. void LLGroupMgr::processGroupBanRequest(const LLSD& content)
  1932. {
  1933. // Did we get anything in content ?
  1934. if (!content.size())
  1935. {
  1936. llwarns << "No group member data received." << llendl;
  1937. return;
  1938. }
  1939. LLUUID group_id = content["group_id"].asUUID();
  1940. LLGroupMgrGroupData* gdatap = gGroupMgr.getGroupData(group_id);
  1941. if (!gdatap) return;
  1942. gdatap->clearBanList();
  1943. for (LLSD::map_const_iterator iter = content["ban_list"].beginMap(),
  1944. end = content["ban_list"].endMap();
  1945. iter != end; ++iter)
  1946. {
  1947. const LLUUID ban_id(iter->first);
  1948. LLSD ban_entry(iter->second);
  1949. LLGroupBanData ban_data;
  1950. if (ban_entry.has("ban_date"))
  1951. {
  1952. ban_data.mBanDate = ban_entry["ban_date"].asDate();
  1953. // *TODO: Ban reason
  1954. }
  1955. gdatap->createBanEntry(ban_id, ban_data);
  1956. }
  1957. gdatap->mChanged = true;
  1958. gGroupMgr.notifyObservers(GC_BANLIST);
  1959. }
  1960. //static
  1961. void LLGroupMgr::groupMembersRequestCoro(const std::string& url,
  1962. const LLUUID& group_id)
  1963. {
  1964. gGroupMgr.mMemberRequestInFlight = true;
  1965. LLSD body = LLSD::emptyMap();
  1966. body["group_id"] = group_id;
  1967. LLCoreHttpUtil::HttpCoroutineAdapter adapter("groupMembersRequest");
  1968. LLSD result = adapter.postAndSuspend(url, body);
  1969. const LLSD& http_results =
  1970. result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
  1971. LLCore::HttpStatus status =
  1972. LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(http_results);
  1973. if (status)
  1974. {
  1975. result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
  1976. processCapGroupMembersRequest(result);
  1977. }
  1978. else
  1979. {
  1980. llwarns << "Error receiving group member data: " << status.toString()
  1981. << llendl;
  1982. }
  1983. gGroupMgr.mMemberRequestInFlight = false;
  1984. }
  1985. //static
  1986. void LLGroupMgr::sendCapGroupMembersRequest(const LLUUID& group_id)
  1987. {
  1988. // Are we requesting the information already ?
  1989. if (mMemberRequestInFlight ||
  1990. // or did we request it in the last 0.5 seconds ?
  1991. mLastGroupMembersRequestTime + 0.5f > gFrameTimeSeconds)
  1992. {
  1993. return;
  1994. }
  1995. mLastGroupMembersRequestTime = gFrameTimeSeconds;
  1996. if (!gSavedSettings.getBool("UseHTTPGroupDataFetch"))
  1997. {
  1998. sendGroupMembersRequest(group_id);
  1999. return;
  2000. }
  2001. // Get our capability
  2002. const std::string& cap_url = gAgent.getRegionCapability("GroupMemberData");
  2003. if (cap_url.empty())
  2004. {
  2005. LL_DEBUGS("GroupMgr") << "Region has no GroupMemberData capability. Falling back to UDP fetch."
  2006. << LL_ENDL;
  2007. sendGroupMembersRequest(group_id);
  2008. return;
  2009. }
  2010. LL_DEBUGS("GroupMgr") << "Region has GroupMemberData capability. Using it."
  2011. << LL_ENDL;
  2012. // Make sure group exists
  2013. LLGroupMgrGroupData* group_datap = createGroupData(group_id);
  2014. group_datap->mMemberRequestID.generate(); // Mark as pending
  2015. gCoros.launch("LLGroupMgr::groupMembersRequestCoro",
  2016. boost::bind(&LLGroupMgr::groupMembersRequestCoro, cap_url,
  2017. group_id));
  2018. }
  2019. //static
  2020. void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)
  2021. {
  2022. // Did we get anything in content ?
  2023. if (!content.size())
  2024. {
  2025. LL_DEBUGS("GroupMgr") << "No group member data received." << LL_ENDL;
  2026. return;
  2027. }
  2028. LLUUID group_id = content["group_id"].asUUID();
  2029. LLGroupMgrGroupData* gdatap = gGroupMgr.getGroupData(group_id);
  2030. if (!gdatap)
  2031. {
  2032. llwarns << "Received incorrect, possibly stale, group or request Id"
  2033. << llendl;
  2034. return;
  2035. }
  2036. // If we have no members, there is no reason to do anything else
  2037. S32 num_members = content["member_count"];
  2038. if (num_members < 1)
  2039. {
  2040. llinfos << "Received empty group members list for group id: " << group_id
  2041. << llendl;
  2042. gdatap->mMemberDataComplete = true;
  2043. gdatap->mChanged = true;
  2044. gGroupMgr.notifyObservers(GC_MEMBER_DATA);
  2045. return;
  2046. }
  2047. gdatap->mMemberCount = num_members;
  2048. LLSD member_list = content["members"];
  2049. LLSD titles = content["titles"];
  2050. LLSD defaults = content["defaults"];
  2051. std::string online_status;
  2052. std::string title;
  2053. S32 contribution;
  2054. U64 member_powers;
  2055. // If this is changed to a bool, make sure to change the LLGroupMemberData
  2056. // constructor
  2057. bool is_owner;
  2058. // Compute this once, rather than every time.
  2059. U64 default_powers =
  2060. llstrtou64(defaults["default_powers"].asString().c_str(), NULL, 16);
  2061. std::string date_format = gSavedSettings.getString("ShortDateFormat");
  2062. LLSD::map_const_iterator member_iter_start = member_list.beginMap();
  2063. LLSD::map_const_iterator member_iter_end = member_list.endMap();
  2064. for ( ; member_iter_start != member_iter_end; ++member_iter_start)
  2065. {
  2066. // Reset defaults
  2067. online_status = "unknown";
  2068. title = titles[0].asString();
  2069. contribution = 0;
  2070. member_powers = default_powers;
  2071. is_owner = false;
  2072. const LLUUID member_id(member_iter_start->first);
  2073. LLSD member_info = member_iter_start->second;
  2074. if (member_info.has("last_login"))
  2075. {
  2076. tm t;
  2077. online_status = member_info["last_login"].asString();
  2078. if (online_status != "Online" &&
  2079. sscanf(online_status.c_str(), "%u/%u/%u", &t.tm_mon,
  2080. &t.tm_mday, &t.tm_year) == 3 && t.tm_year > 1900)
  2081. {
  2082. t.tm_year -= 1900;
  2083. --t.tm_mon;
  2084. t.tm_hour = t.tm_min = t.tm_sec = 0;
  2085. timeStructToFormattedString(&t, date_format, online_status);
  2086. }
  2087. }
  2088. if (member_info.has("title"))
  2089. {
  2090. title = titles[member_info["title"].asInteger()].asString();
  2091. }
  2092. if (member_info.has("powers"))
  2093. {
  2094. member_powers = llstrtou64(member_info["powers"].asString().c_str(),
  2095. NULL, 16);
  2096. }
  2097. if (member_info.has("donated_square_meters"))
  2098. {
  2099. contribution = member_info["donated_square_meters"];
  2100. }
  2101. if (member_info.has("owner"))
  2102. {
  2103. is_owner = true;
  2104. }
  2105. LLGroupMemberData* data = new LLGroupMemberData(member_id,
  2106. contribution,
  2107. member_powers,
  2108. title,
  2109. online_status,
  2110. is_owner);
  2111. LLGroupMemberData* member_old = gdatap->mMembers[member_id];
  2112. if (member_old && gdatap->mRoleMemberDataComplete)
  2113. {
  2114. for (LLGroupMemberData::role_list_t::iterator
  2115. it = member_old->roleBegin(), end = member_old->roleEnd();
  2116. it != end; ++it)
  2117. {
  2118. data->addRole(it->first, it->second);
  2119. }
  2120. }
  2121. else
  2122. {
  2123. gdatap->mRoleMemberDataComplete = false;
  2124. }
  2125. gdatap->mMembers[member_id] = data;
  2126. }
  2127. // Technically, we have this data, but to prevent completely overhauling
  2128. // this entire system (it would be nice, but I do not have the time),
  2129. // I am going to be dumb and just call services I most likely do not need
  2130. // with the thought being that the system might need it to be done.
  2131. //
  2132. // TODO:
  2133. // Refactor to reduce multiple calls for data we already have.
  2134. if (gdatap->mTitles.empty())
  2135. {
  2136. gGroupMgr.sendGroupTitlesRequest(group_id);
  2137. }
  2138. gdatap->mMemberDataComplete = true;
  2139. gdatap->mMemberRequestID.setNull();
  2140. // Make the role-member data request
  2141. if (gdatap->mPendingRoleMemberRequest ||
  2142. !gdatap->mRoleMemberDataComplete)
  2143. {
  2144. gdatap->mPendingRoleMemberRequest = false;
  2145. gGroupMgr.sendGroupRoleMembersRequest(group_id);
  2146. }
  2147. gdatap->mChanged = true;
  2148. gGroupMgr.notifyObservers(GC_MEMBER_DATA);
  2149. }
  2150. void LLGroupMgr::sendGroupRoleChanges(const LLUUID& group_id)
  2151. {
  2152. LLGroupMgrGroupData* gdatap = getGroupData(group_id);
  2153. if (gdatap && gdatap->pendingRoleChanges())
  2154. {
  2155. gdatap->sendRoleChanges();
  2156. // Not expecting a response, so let anyone else watching know the data
  2157. // has changed.
  2158. gdatap->mChanged = true;
  2159. notifyObservers(GC_ROLE_DATA);
  2160. }
  2161. }
  2162. void LLGroupMgr::cancelGroupRoleChanges(const LLUUID& group_id)
  2163. {
  2164. LLGroupMgrGroupData* gdatap = getGroupData(group_id);
  2165. if (gdatap)
  2166. {
  2167. gdatap->cancelRoleChanges();
  2168. }
  2169. }
  2170. //static
  2171. bool LLGroupMgr::parseRoleActions(const std::string& xml_filename)
  2172. {
  2173. LLXMLNodePtr root;
  2174. bool success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root);
  2175. if (!success || !root || !root->hasName("role_actions"))
  2176. {
  2177. llerrs << "Problem reading UI role_actions file: " << xml_filename
  2178. << llendl;
  2179. return false;
  2180. }
  2181. LLXMLNodeList role_list;
  2182. root->getChildren("action_set", role_list, false);
  2183. for (LLXMLNodeList::iterator role_iter = role_list.begin();
  2184. role_iter != role_list.end(); ++role_iter)
  2185. {
  2186. LLXMLNodePtr action_set = role_iter->second;
  2187. LLRoleActionSet* role_action_set = new LLRoleActionSet();
  2188. LLRoleAction* role_action_data = new LLRoleAction();
  2189. // name=
  2190. std::string action_set_name;
  2191. if (action_set->getAttributeString("name", action_set_name))
  2192. {
  2193. LL_DEBUGS("GroupMgr") << "Loading action set " << action_set_name
  2194. << LL_ENDL;
  2195. role_action_data->mName = action_set_name;
  2196. }
  2197. else
  2198. {
  2199. llwarns << "Unable to parse action set with no name" << llendl;
  2200. delete role_action_set;
  2201. delete role_action_data;
  2202. continue;
  2203. }
  2204. // description=
  2205. std::string set_description;
  2206. if (action_set->getAttributeString("description", set_description))
  2207. {
  2208. role_action_data->mDescription = set_description;
  2209. }
  2210. // long description=
  2211. std::string set_longdescription;
  2212. if (action_set->getAttributeString("longdescription",
  2213. set_longdescription))
  2214. {
  2215. role_action_data->mLongDescription = set_longdescription;
  2216. }
  2217. // power mask=
  2218. U64 set_power_mask = 0;
  2219. LLXMLNodeList action_list;
  2220. LLXMLNodeList::iterator action_iter;
  2221. action_set->getChildren("action", action_list, false);
  2222. for (action_iter = action_list.begin();
  2223. action_iter != action_list.end(); ++action_iter)
  2224. {
  2225. LLXMLNodePtr action = action_iter->second;
  2226. LLRoleAction* role_action = new LLRoleAction();
  2227. // name=
  2228. std::string action_name;
  2229. if (action->getAttributeString("name", action_name))
  2230. {
  2231. LL_DEBUGS("GroupMgr") << "Loading action " << action_name
  2232. << LL_ENDL;
  2233. role_action->mName = action_name;
  2234. }
  2235. else
  2236. {
  2237. llwarns << "Unable to parse action with no name" << llendl;
  2238. delete role_action;
  2239. continue;
  2240. }
  2241. // description=
  2242. std::string description;
  2243. if (action->getAttributeString("description", description))
  2244. {
  2245. role_action->mDescription = description;
  2246. }
  2247. // long description=
  2248. std::string longdescription;
  2249. if (action->getAttributeString("longdescription", longdescription))
  2250. {
  2251. role_action->mLongDescription = longdescription;
  2252. }
  2253. // description=
  2254. S32 power_bit = 0;
  2255. if (action->getAttributeS32("value", power_bit))
  2256. {
  2257. if (0 <= power_bit && power_bit < 64)
  2258. {
  2259. role_action->mPowerBit = 0x1LL << power_bit;
  2260. }
  2261. }
  2262. set_power_mask |= role_action->mPowerBit;
  2263. role_action_set->mActions.push_back(role_action);
  2264. }
  2265. role_action_data->mPowerBit = set_power_mask;
  2266. role_action_set->mActionSetData = role_action_data;
  2267. gGroupMgr.mRoleActionSets.push_back(role_action_set);
  2268. }
  2269. return true;
  2270. }
  2271. //static
  2272. void LLGroupMgr::debugClearAllGroups(void*)
  2273. {
  2274. gGroupMgr.clearGroups();
  2275. LLGroupMgr::parseRoleActions("role_actions.xml");
  2276. }