PageRenderTime 45ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/newview/llgroupmgr.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1951 lines | 1523 code | 276 blank | 152 comment | 270 complexity | e00fc6792d6c32595b64fa858b867823 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llgroupmgr.cpp
  3. * @brief LLGroupMgr class implementation
  4. *
  5. * $LicenseInfo:firstyear=2004&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. /**
  27. * Manager for aggregating all client knowledge for specific groups
  28. * Keeps a cache of group information.
  29. */
  30. #include "llviewerprecompiledheaders.h"
  31. #include "llgroupmgr.h"
  32. #include <vector>
  33. #include <algorithm>
  34. #include "llagent.h"
  35. #include "llui.h"
  36. #include "message.h"
  37. #include "roles_constants.h"
  38. #include "lltransactiontypes.h"
  39. #include "llstatusbar.h"
  40. #include "lleconomy.h"
  41. #include "llviewerwindow.h"
  42. #include "llpanelgroup.h"
  43. #include "llgroupactions.h"
  44. #include "llnotificationsutil.h"
  45. #include "lluictrlfactory.h"
  46. #include "lltrans.h"
  47. #include <boost/regex.hpp>
  48. #if LL_MSVC
  49. #pragma warning(push)
  50. // disable boost::lexical_cast warning
  51. #pragma warning (disable:4702)
  52. #endif
  53. #include <boost/lexical_cast.hpp>
  54. #if LL_MSVC
  55. #pragma warning(pop) // Restore all warnings to the previous state
  56. #endif
  57. const U32 MAX_CACHED_GROUPS = 10;
  58. //
  59. // LLRoleActionSet
  60. //
  61. LLRoleActionSet::LLRoleActionSet()
  62. : mActionSetData(NULL)
  63. { }
  64. LLRoleActionSet::~LLRoleActionSet()
  65. {
  66. delete mActionSetData;
  67. std::for_each(mActions.begin(), mActions.end(), DeletePointer());
  68. }
  69. //
  70. // LLGroupMemberData
  71. //
  72. LLGroupMemberData::LLGroupMemberData(const LLUUID& id,
  73. S32 contribution,
  74. U64 agent_powers,
  75. const std::string& title,
  76. const std::string& online_status,
  77. BOOL is_owner) :
  78. mID(id),
  79. mContribution(contribution),
  80. mAgentPowers(agent_powers),
  81. mTitle(title),
  82. mOnlineStatus(online_status),
  83. mIsOwner(is_owner)
  84. {
  85. }
  86. LLGroupMemberData::~LLGroupMemberData()
  87. {
  88. }
  89. void LLGroupMemberData::addRole(const LLUUID& role, LLGroupRoleData* rd)
  90. {
  91. mRolesList[role] = rd;
  92. }
  93. bool LLGroupMemberData::removeRole(const LLUUID& role)
  94. {
  95. role_list_t::iterator it = mRolesList.find(role);
  96. if (it != mRolesList.end())
  97. {
  98. mRolesList.erase(it);
  99. return true;
  100. }
  101. return false;
  102. }
  103. //
  104. // LLGroupRoleData
  105. //
  106. LLGroupRoleData::LLGroupRoleData(const LLUUID& role_id,
  107. const std::string& role_name,
  108. const std::string& role_title,
  109. const std::string& role_desc,
  110. const U64 role_powers,
  111. const S32 member_count) :
  112. mRoleID(role_id),
  113. mMemberCount(member_count),
  114. mMembersNeedsSort(FALSE)
  115. {
  116. mRoleData.mRoleName = role_name;
  117. mRoleData.mRoleTitle = role_title;
  118. mRoleData.mRoleDescription = role_desc;
  119. mRoleData.mRolePowers = role_powers;
  120. mRoleData.mChangeType = RC_UPDATE_NONE;
  121. }
  122. LLGroupRoleData::LLGroupRoleData(const LLUUID& role_id,
  123. LLRoleData role_data,
  124. const S32 member_count) :
  125. mRoleID(role_id),
  126. mRoleData(role_data),
  127. mMemberCount(member_count),
  128. mMembersNeedsSort(FALSE)
  129. {
  130. }
  131. LLGroupRoleData::~LLGroupRoleData()
  132. {
  133. }
  134. S32 LLGroupRoleData::getMembersInRole(uuid_vec_t members,
  135. BOOL needs_sort)
  136. {
  137. if (mRoleID.isNull())
  138. {
  139. // This is the everyone role, just return the size of members,
  140. // because everyone is in the everyone role.
  141. return members.size();
  142. }
  143. // Sort the members list, if needed.
  144. if (mMembersNeedsSort)
  145. {
  146. std::sort(mMemberIDs.begin(), mMemberIDs.end());
  147. mMembersNeedsSort = FALSE;
  148. }
  149. if (needs_sort)
  150. {
  151. // Sort the members parameter.
  152. std::sort(members.begin(), members.end());
  153. }
  154. // Return the number of members in the intersection.
  155. S32 max_size = llmin( members.size(), mMemberIDs.size() );
  156. uuid_vec_t in_role( max_size );
  157. uuid_vec_t::iterator in_role_end;
  158. in_role_end = std::set_intersection(mMemberIDs.begin(), mMemberIDs.end(),
  159. members.begin(), members.end(),
  160. in_role.begin());
  161. return in_role_end - in_role.begin();
  162. }
  163. void LLGroupRoleData::addMember(const LLUUID& member)
  164. {
  165. mMembersNeedsSort = TRUE;
  166. mMemberIDs.push_back(member);
  167. }
  168. bool LLGroupRoleData::removeMember(const LLUUID& member)
  169. {
  170. uuid_vec_t::iterator it = std::find(mMemberIDs.begin(),mMemberIDs.end(),member);
  171. if (it != mMemberIDs.end())
  172. {
  173. mMembersNeedsSort = TRUE;
  174. mMemberIDs.erase(it);
  175. return true;
  176. }
  177. return false;
  178. }
  179. void LLGroupRoleData::clearMembers()
  180. {
  181. mMembersNeedsSort = FALSE;
  182. mMemberIDs.clear();
  183. }
  184. //
  185. // LLGroupMgrGroupData
  186. //
  187. LLGroupMgrGroupData::LLGroupMgrGroupData(const LLUUID& id) :
  188. mID(id),
  189. mShowInList(TRUE),
  190. mOpenEnrollment(FALSE),
  191. mMembershipFee(0),
  192. mAllowPublish(FALSE),
  193. mListInProfile(FALSE),
  194. mMaturePublish(FALSE),
  195. mChanged(FALSE),
  196. mMemberCount(0),
  197. mRoleCount(0),
  198. mReceivedRoleMemberPairs(0),
  199. mMemberDataComplete(FALSE),
  200. mRoleDataComplete(FALSE),
  201. mRoleMemberDataComplete(FALSE),
  202. mGroupPropertiesDataComplete(FALSE),
  203. mPendingRoleMemberRequest(FALSE)
  204. {
  205. }
  206. BOOL LLGroupMgrGroupData::getRoleData(const LLUUID& role_id, LLRoleData& role_data)
  207. {
  208. role_data_map_t::const_iterator it;
  209. // Do we have changes for it?
  210. it = mRoleChanges.find(role_id);
  211. if (it != mRoleChanges.end())
  212. {
  213. if ((*it).second.mChangeType == RC_DELETE) return FALSE;
  214. role_data = (*it).second;
  215. return TRUE;
  216. }
  217. // Ok, no changes, hasn't been deleted, isn't a new role, just find the role.
  218. role_list_t::const_iterator rit = mRoles.find(role_id);
  219. if (rit != mRoles.end())
  220. {
  221. role_data = (*rit).second->getRoleData();
  222. return TRUE;
  223. }
  224. // This role must not exist.
  225. return FALSE;
  226. }
  227. void LLGroupMgrGroupData::setRoleData(const LLUUID& role_id, LLRoleData role_data)
  228. {
  229. // If this is a newly created group, we need to change the data in the created list.
  230. role_data_map_t::iterator it;
  231. it = mRoleChanges.find(role_id);
  232. if (it != mRoleChanges.end())
  233. {
  234. if ((*it).second.mChangeType == RC_CREATE)
  235. {
  236. role_data.mChangeType = RC_CREATE;
  237. mRoleChanges[role_id] = role_data;
  238. return;
  239. }
  240. else if ((*it).second.mChangeType == RC_DELETE)
  241. {
  242. // Don't do anything for a role being deleted.
  243. return;
  244. }
  245. }
  246. // Not a new role, so put it in the changes list.
  247. LLRoleData old_role_data;
  248. role_list_t::iterator rit = mRoles.find(role_id);
  249. if (rit != mRoles.end())
  250. {
  251. bool data_change = ( ((*rit).second->mRoleData.mRoleDescription != role_data.mRoleDescription)
  252. || ((*rit).second->mRoleData.mRoleName != role_data.mRoleName)
  253. || ((*rit).second->mRoleData.mRoleTitle != role_data.mRoleTitle) );
  254. bool powers_change = ((*rit).second->mRoleData.mRolePowers != role_data.mRolePowers);
  255. if (!data_change && !powers_change)
  256. {
  257. // We are back to the original state, the changes have been 'undone' so take out the change.
  258. mRoleChanges.erase(role_id);
  259. return;
  260. }
  261. if (data_change && powers_change)
  262. {
  263. role_data.mChangeType = RC_UPDATE_ALL;
  264. }
  265. else if (data_change)
  266. {
  267. role_data.mChangeType = RC_UPDATE_DATA;
  268. }
  269. else
  270. {
  271. role_data.mChangeType = RC_UPDATE_POWERS;
  272. }
  273. mRoleChanges[role_id] = role_data;
  274. }
  275. else
  276. {
  277. llwarns << "Change being made to non-existant role " << role_id << llendl;
  278. }
  279. }
  280. BOOL LLGroupMgrGroupData::pendingRoleChanges()
  281. {
  282. return (!mRoleChanges.empty());
  283. }
  284. // This is a no-op if the role has already been created.
  285. void LLGroupMgrGroupData::createRole(const LLUUID& role_id, LLRoleData role_data)
  286. {
  287. if (mRoleChanges.find(role_id) != mRoleChanges.end())
  288. {
  289. llwarns << "create role for existing role! " << role_id << llendl;
  290. }
  291. else
  292. {
  293. role_data.mChangeType = RC_CREATE;
  294. mRoleChanges[role_id] = role_data;
  295. }
  296. }
  297. void LLGroupMgrGroupData::deleteRole(const LLUUID& role_id)
  298. {
  299. role_data_map_t::iterator it;
  300. // If this was a new role, just discard it.
  301. it = mRoleChanges.find(role_id);
  302. if (it != mRoleChanges.end()
  303. && (*it).second.mChangeType == RC_CREATE)
  304. {
  305. mRoleChanges.erase(it);
  306. return;
  307. }
  308. LLRoleData rd;
  309. rd.mChangeType = RC_DELETE;
  310. mRoleChanges[role_id] = rd;
  311. }
  312. void LLGroupMgrGroupData::addRolePower(const LLUUID &role_id, U64 power)
  313. {
  314. LLRoleData rd;
  315. if (getRoleData(role_id,rd))
  316. {
  317. rd.mRolePowers |= power;
  318. setRoleData(role_id,rd);
  319. }
  320. else
  321. {
  322. llwarns << "addRolePower: no role data found for " << role_id << llendl;
  323. }
  324. }
  325. void LLGroupMgrGroupData::removeRolePower(const LLUUID &role_id, U64 power)
  326. {
  327. LLRoleData rd;
  328. if (getRoleData(role_id,rd))
  329. {
  330. rd.mRolePowers &= ~power;
  331. setRoleData(role_id,rd);
  332. }
  333. else
  334. {
  335. llwarns << "removeRolePower: no role data found for " << role_id << llendl;
  336. }
  337. }
  338. U64 LLGroupMgrGroupData::getRolePowers(const LLUUID& role_id)
  339. {
  340. LLRoleData rd;
  341. if (getRoleData(role_id,rd))
  342. {
  343. return rd.mRolePowers;
  344. }
  345. else
  346. {
  347. llwarns << "getRolePowers: no role data found for " << role_id << llendl;
  348. return GP_NO_POWERS;
  349. }
  350. }
  351. void LLGroupMgrGroupData::removeData()
  352. {
  353. // Remove member data first, because removeRoleData will walk the member list
  354. removeMemberData();
  355. removeRoleData();
  356. }
  357. void LLGroupMgrGroupData::removeMemberData()
  358. {
  359. for (member_list_t::iterator mi = mMembers.begin(); mi != mMembers.end(); ++mi)
  360. {
  361. delete mi->second;
  362. }
  363. mMembers.clear();
  364. mMemberDataComplete = FALSE;
  365. }
  366. void LLGroupMgrGroupData::removeRoleData()
  367. {
  368. for (member_list_t::iterator mi = mMembers.begin(); mi != mMembers.end(); ++mi)
  369. {
  370. LLGroupMemberData* data = mi->second;
  371. if (data)
  372. {
  373. data->clearRoles();
  374. }
  375. }
  376. for (role_list_t::iterator ri = mRoles.begin(); ri != mRoles.end(); ++ri)
  377. {
  378. LLGroupRoleData* data = ri->second;
  379. delete data;
  380. }
  381. mRoles.clear();
  382. mReceivedRoleMemberPairs = 0;
  383. mRoleDataComplete = FALSE;
  384. mRoleMemberDataComplete = FALSE;
  385. }
  386. void LLGroupMgrGroupData::removeRoleMemberData()
  387. {
  388. for (member_list_t::iterator mi = mMembers.begin(); mi != mMembers.end(); ++mi)
  389. {
  390. LLGroupMemberData* data = mi->second;
  391. if (data)
  392. {
  393. data->clearRoles();
  394. }
  395. }
  396. for (role_list_t::iterator ri = mRoles.begin(); ri != mRoles.end(); ++ri)
  397. {
  398. LLGroupRoleData* data = ri->second;
  399. if (data)
  400. {
  401. data->clearMembers();
  402. }
  403. }
  404. mReceivedRoleMemberPairs = 0;
  405. mRoleMemberDataComplete = FALSE;
  406. }
  407. LLGroupMgrGroupData::~LLGroupMgrGroupData()
  408. {
  409. removeData();
  410. }
  411. bool LLGroupMgrGroupData::changeRoleMember(const LLUUID& role_id,
  412. const LLUUID& member_id,
  413. LLRoleMemberChangeType rmc)
  414. {
  415. role_list_t::iterator ri = mRoles.find(role_id);
  416. member_list_t::iterator mi = mMembers.find(member_id);
  417. if (ri == mRoles.end()
  418. || mi == mMembers.end() )
  419. {
  420. if (ri == mRoles.end()) llwarns << "LLGroupMgrGroupData::changeRoleMember couldn't find role " << role_id << llendl;
  421. if (mi == mMembers.end()) llwarns << "LLGroupMgrGroupData::changeRoleMember couldn't find member " << member_id << llendl;
  422. return false;
  423. }
  424. LLGroupRoleData* grd = ri->second;
  425. LLGroupMemberData* gmd = mi->second;
  426. if (!grd || !gmd)
  427. {
  428. llwarns << "LLGroupMgrGroupData::changeRoleMember couldn't get member or role data." << llendl;
  429. return false;
  430. }
  431. if (RMC_ADD == rmc)
  432. {
  433. llinfos << " adding member to role." << llendl;
  434. grd->addMember(member_id);
  435. gmd->addRole(role_id,grd);
  436. //TODO move this into addrole function
  437. //see if they added someone to the owner role and update isOwner
  438. gmd->mIsOwner = (role_id == mOwnerRole) ? TRUE : gmd->mIsOwner;
  439. }
  440. else if (RMC_REMOVE == rmc)
  441. {
  442. llinfos << " removing member from role." << llendl;
  443. grd->removeMember(member_id);
  444. gmd->removeRole(role_id);
  445. //see if they removed someone from the owner role and update isOwner
  446. gmd->mIsOwner = (role_id == mOwnerRole) ? FALSE : gmd->mIsOwner;
  447. }
  448. lluuid_pair role_member;
  449. role_member.first = role_id;
  450. role_member.second = member_id;
  451. change_map_t::iterator it = mRoleMemberChanges.find(role_member);
  452. if (it != mRoleMemberChanges.end())
  453. {
  454. // There was already a role change for this role_member
  455. if (it->second.mChange == rmc)
  456. {
  457. // Already recorded this change? Weird.
  458. llinfos << "Received duplicate change for "
  459. << " role: " << role_id << " member " << member_id
  460. << " change " << (rmc == RMC_ADD ? "ADD" : "REMOVE") << llendl;
  461. }
  462. else
  463. {
  464. // The only two operations (add and remove) currently cancel each other out
  465. // If that changes this will need more logic
  466. if (rmc == RMC_NONE)
  467. {
  468. llwarns << "changeRoleMember: existing entry with 'RMC_NONE' change! This shouldn't happen." << llendl;
  469. LLRoleMemberChange rc(role_id,member_id,rmc);
  470. mRoleMemberChanges[role_member] = rc;
  471. }
  472. else
  473. {
  474. mRoleMemberChanges.erase(it);
  475. }
  476. }
  477. }
  478. else
  479. {
  480. LLRoleMemberChange rc(role_id,member_id,rmc);
  481. mRoleMemberChanges[role_member] = rc;
  482. }
  483. recalcAgentPowers(member_id);
  484. mChanged = TRUE;
  485. return true;
  486. }
  487. void LLGroupMgrGroupData::recalcAllAgentPowers()
  488. {
  489. LLGroupMemberData* gmd;
  490. for (member_list_t::iterator mit = mMembers.begin();
  491. mit != mMembers.end(); ++mit)
  492. {
  493. gmd = mit->second;
  494. if (!gmd) continue;
  495. gmd->mAgentPowers = 0;
  496. for (LLGroupMemberData::role_list_t::iterator it = gmd->mRolesList.begin();
  497. it != gmd->mRolesList.end(); ++it)
  498. {
  499. LLGroupRoleData* grd = (*it).second;
  500. if (!grd) continue;
  501. gmd->mAgentPowers |= grd->mRoleData.mRolePowers;
  502. }
  503. }
  504. }
  505. void LLGroupMgrGroupData::recalcAgentPowers(const LLUUID& agent_id)
  506. {
  507. member_list_t::iterator mi = mMembers.find(agent_id);
  508. if (mi == mMembers.end()) return;
  509. LLGroupMemberData* gmd = mi->second;
  510. if (!gmd) return;
  511. gmd->mAgentPowers = 0;
  512. for (LLGroupMemberData::role_list_t::iterator it = gmd->mRolesList.begin();
  513. it != gmd->mRolesList.end(); ++it)
  514. {
  515. LLGroupRoleData* grd = (*it).second;
  516. if (!grd) continue;
  517. gmd->mAgentPowers |= grd->mRoleData.mRolePowers;
  518. }
  519. }
  520. bool packRoleUpdateMessageBlock(LLMessageSystem* msg,
  521. const LLUUID& group_id,
  522. const LLUUID& role_id,
  523. const LLRoleData& role_data,
  524. bool start_message)
  525. {
  526. if (start_message)
  527. {
  528. msg->newMessage("GroupRoleUpdate");
  529. msg->nextBlock("AgentData");
  530. msg->addUUID("AgentID",gAgent.getID());
  531. msg->addUUID("SessionID",gAgent.getSessionID());
  532. msg->addUUID("GroupID",group_id);
  533. start_message = false;
  534. }
  535. msg->nextBlock("RoleData");
  536. msg->addUUID("RoleID",role_id);
  537. msg->addString("Name", role_data.mRoleName);
  538. msg->addString("Description", role_data.mRoleDescription);
  539. msg->addString("Title", role_data.mRoleTitle);
  540. msg->addU64("Powers", role_data.mRolePowers);
  541. msg->addU8("UpdateType", (U8)role_data.mChangeType);
  542. if (msg->isSendFullFast())
  543. {
  544. gAgent.sendReliableMessage();
  545. start_message = true;
  546. }
  547. return start_message;
  548. }
  549. void LLGroupMgrGroupData::sendRoleChanges()
  550. {
  551. // Commit changes locally
  552. LLGroupRoleData* grd;
  553. role_list_t::iterator role_it;
  554. LLMessageSystem* msg = gMessageSystem;
  555. bool start_message = true;
  556. bool need_role_cleanup = false;
  557. bool need_role_data = false;
  558. bool need_power_recalc = false;
  559. // Apply all changes
  560. for (role_data_map_t::iterator iter = mRoleChanges.begin();
  561. iter != mRoleChanges.end(); )
  562. {
  563. role_data_map_t::iterator it = iter++; // safely incrament iter
  564. const LLUUID& role_id = (*it).first;
  565. const LLRoleData& role_data = (*it).second;
  566. // Commit to local data set
  567. role_it = mRoles.find((*it).first);
  568. if ( (mRoles.end() == role_it
  569. && RC_CREATE != role_data.mChangeType)
  570. || (mRoles.end() != role_it
  571. && RC_CREATE == role_data.mChangeType))
  572. {
  573. continue;
  574. }
  575. // NOTE: role_it is valid EXCEPT for the RC_CREATE case
  576. switch (role_data.mChangeType)
  577. {
  578. case RC_CREATE:
  579. {
  580. // NOTE: role_it is NOT valid in this case
  581. grd = new LLGroupRoleData(role_id, role_data, 0);
  582. mRoles[role_id] = grd;
  583. need_role_data = true;
  584. break;
  585. }
  586. case RC_DELETE:
  587. {
  588. LLGroupRoleData* group_role_data = (*role_it).second;
  589. delete group_role_data;
  590. mRoles.erase(role_it);
  591. need_role_cleanup = true;
  592. need_power_recalc = true;
  593. break;
  594. }
  595. case RC_UPDATE_ALL:
  596. // fall through
  597. case RC_UPDATE_POWERS:
  598. need_power_recalc = true;
  599. // fall through
  600. case RC_UPDATE_DATA:
  601. // fall through
  602. default:
  603. {
  604. LLGroupRoleData* group_role_data = (*role_it).second;
  605. group_role_data->setRoleData(role_data); // NOTE! might modify mRoleChanges!
  606. break;
  607. }
  608. }
  609. // Update dataserver
  610. start_message = packRoleUpdateMessageBlock(msg,getID(),role_id,role_data,start_message);
  611. }
  612. if (!start_message)
  613. {
  614. gAgent.sendReliableMessage();
  615. }
  616. // If we delete a role then all the role-member pairs are invalid!
  617. if (need_role_cleanup)
  618. {
  619. removeRoleMemberData();
  620. }
  621. // If we create a new role, then we need to re-fetch all the role data.
  622. if (need_role_data)
  623. {
  624. LLGroupMgr::getInstance()->sendGroupRoleDataRequest(getID());
  625. }
  626. // Clean up change lists
  627. mRoleChanges.clear();
  628. // Recalculate all the agent powers because role powers have now changed.
  629. if (need_power_recalc)
  630. {
  631. recalcAllAgentPowers();
  632. }
  633. }
  634. void LLGroupMgrGroupData::cancelRoleChanges()
  635. {
  636. // Clear out all changes!
  637. mRoleChanges.clear();
  638. }
  639. //
  640. // LLGroupMgr
  641. //
  642. LLGroupMgr::LLGroupMgr()
  643. {
  644. }
  645. LLGroupMgr::~LLGroupMgr()
  646. {
  647. clearGroups();
  648. }
  649. void LLGroupMgr::clearGroups()
  650. {
  651. std::for_each(mRoleActionSets.begin(), mRoleActionSets.end(), DeletePointer());
  652. mRoleActionSets.clear();
  653. std::for_each(mGroups.begin(), mGroups.end(), DeletePairedPointer());
  654. mGroups.clear();
  655. mObservers.clear();
  656. }
  657. void LLGroupMgr::clearGroupData(const LLUUID& group_id)
  658. {
  659. group_map_t::iterator iter = mGroups.find(group_id);
  660. if (iter != mGroups.end())
  661. {
  662. delete (*iter).second;
  663. mGroups.erase(iter);
  664. }
  665. }
  666. void LLGroupMgr::addObserver(LLGroupMgrObserver* observer)
  667. {
  668. if( observer->getID() != LLUUID::null )
  669. mObservers.insert(std::pair<LLUUID, LLGroupMgrObserver*>(observer->getID(), observer));
  670. }
  671. void LLGroupMgr::addObserver(const LLUUID& group_id, LLParticularGroupObserver* observer)
  672. {
  673. if(group_id.notNull() && observer)
  674. {
  675. mParticularObservers[group_id].insert(observer);
  676. }
  677. }
  678. void LLGroupMgr::removeObserver(LLGroupMgrObserver* observer)
  679. {
  680. if (!observer)
  681. {
  682. return;
  683. }
  684. observer_multimap_t::iterator it;
  685. it = mObservers.find(observer->getID());
  686. while (it != mObservers.end())
  687. {
  688. if (it->second == observer)
  689. {
  690. mObservers.erase(it);
  691. break;
  692. }
  693. else
  694. {
  695. ++it;
  696. }
  697. }
  698. }
  699. void LLGroupMgr::removeObserver(const LLUUID& group_id, LLParticularGroupObserver* observer)
  700. {
  701. if(group_id.isNull() || !observer)
  702. {
  703. return;
  704. }
  705. observer_map_t::iterator obs_it = mParticularObservers.find(group_id);
  706. if(obs_it == mParticularObservers.end())
  707. return;
  708. obs_it->second.erase(observer);
  709. if (obs_it->second.size() == 0)
  710. mParticularObservers.erase(obs_it);
  711. }
  712. LLGroupMgrGroupData* LLGroupMgr::getGroupData(const LLUUID& id)
  713. {
  714. group_map_t::iterator gi = mGroups.find(id);
  715. if (gi != mGroups.end())
  716. {
  717. return gi->second;
  718. }
  719. return NULL;
  720. }
  721. // Helper function for LLGroupMgr::processGroupMembersReply
  722. // This reformats date strings from MM/DD/YYYY to YYYY/MM/DD ( e.g. 1/27/2008 -> 2008/1/27 )
  723. // so that the sorter can sort by year before month before day.
  724. static void formatDateString(std::string &date_string)
  725. {
  726. using namespace boost;
  727. cmatch result;
  728. const regex expression("([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})");
  729. if (regex_match(date_string.c_str(), result, expression))
  730. {
  731. // convert matches to integers so that we can pad them with zeroes on Linux
  732. S32 year = boost::lexical_cast<S32>(result[3]);
  733. S32 month = boost::lexical_cast<S32>(result[1]);
  734. S32 day = boost::lexical_cast<S32>(result[2]);
  735. // ISO 8601 date format
  736. date_string = llformat("%04d/%02d/%02d", year, month, day);
  737. }
  738. }
  739. // static
  740. void LLGroupMgr::processGroupMembersReply(LLMessageSystem* msg, void** data)
  741. {
  742. lldebugs << "LLGroupMgr::processGroupMembersReply" << llendl;
  743. LLUUID agent_id;
  744. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
  745. if (gAgent.getID() != agent_id)
  746. {
  747. llwarns << "Got group members reply for another agent!" << llendl;
  748. return;
  749. }
  750. LLUUID group_id;
  751. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id );
  752. LLUUID request_id;
  753. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_RequestID, request_id);
  754. LLGroupMgrGroupData* group_datap = LLGroupMgr::getInstance()->getGroupData(group_id);
  755. if (!group_datap || (group_datap->mMemberRequestID != request_id))
  756. {
  757. llwarns << "processGroupMembersReply: Received incorrect (stale?) group or request id" << llendl;
  758. return;
  759. }
  760. msg->getS32(_PREHASH_GroupData, "MemberCount", group_datap->mMemberCount );
  761. if (group_datap->mMemberCount > 0)
  762. {
  763. S32 contribution = 0;
  764. std::string online_status;
  765. std::string title;
  766. U64 agent_powers = 0;
  767. BOOL is_owner = FALSE;
  768. S32 num_members = msg->getNumberOfBlocksFast(_PREHASH_MemberData);
  769. for (S32 i = 0; i < num_members; i++)
  770. {
  771. LLUUID member_id;
  772. msg->getUUIDFast(_PREHASH_MemberData, _PREHASH_AgentID, member_id, i );
  773. msg->getS32(_PREHASH_MemberData, _PREHASH_Contribution, contribution, i);
  774. msg->getU64(_PREHASH_MemberData, "AgentPowers", agent_powers, i);
  775. msg->getStringFast(_PREHASH_MemberData, _PREHASH_OnlineStatus, online_status, i);
  776. msg->getString(_PREHASH_MemberData, "Title", title, i);
  777. msg->getBOOL(_PREHASH_MemberData,"IsOwner",is_owner,i);
  778. if (member_id.notNull())
  779. {
  780. if (online_status == "Online")
  781. {
  782. static std::string localized_online(LLTrans::getString("group_member_status_online"));
  783. online_status = localized_online;
  784. }
  785. else
  786. {
  787. formatDateString(online_status); // reformat for sorting, e.g. 12/25/2008 -> 2008/12/25
  788. }
  789. //llinfos << "Member " << member_id << " has powers " << std::hex << agent_powers << std::dec << llendl;
  790. LLGroupMemberData* newdata = new LLGroupMemberData(member_id,
  791. contribution,
  792. agent_powers,
  793. title,
  794. online_status,
  795. is_owner);
  796. #if LL_DEBUG
  797. LLGroupMgrGroupData::member_list_t::iterator mit = group_datap->mMembers.find(member_id);
  798. if (mit != group_datap->mMembers.end())
  799. {
  800. llinfos << " *** Received duplicate member data for agent " << member_id << llendl;
  801. }
  802. #endif
  803. group_datap->mMembers[member_id] = newdata;
  804. }
  805. else
  806. {
  807. llinfos << "Received null group member data." << llendl;
  808. }
  809. }
  810. //if group members are loaded while titles are missing, load the titles.
  811. if(group_datap->mTitles.size() < 1)
  812. {
  813. LLGroupMgr::getInstance()->sendGroupTitlesRequest(group_id);
  814. }
  815. }
  816. if (group_datap->mMembers.size() == (U32)group_datap->mMemberCount)
  817. {
  818. group_datap->mMemberDataComplete = TRUE;
  819. group_datap->mMemberRequestID.setNull();
  820. // We don't want to make role-member data requests until we have all the members
  821. if (group_datap->mPendingRoleMemberRequest)
  822. {
  823. group_datap->mPendingRoleMemberRequest = FALSE;
  824. LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(group_datap->mID);
  825. }
  826. }
  827. group_datap->mChanged = TRUE;
  828. LLGroupMgr::getInstance()->notifyObservers(GC_MEMBER_DATA);
  829. }
  830. //static
  831. void LLGroupMgr::processGroupPropertiesReply(LLMessageSystem* msg, void** data)
  832. {
  833. lldebugs << "LLGroupMgr::processGroupPropertiesReply" << llendl;
  834. LLUUID agent_id;
  835. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
  836. if (gAgent.getID() != agent_id)
  837. {
  838. llwarns << "Got group properties reply for another agent!" << llendl;
  839. return;
  840. }
  841. LLUUID group_id;
  842. std::string name;
  843. std::string charter;
  844. BOOL show_in_list = FALSE;
  845. LLUUID founder_id;
  846. U64 powers_mask = GP_NO_POWERS;
  847. S32 money = 0;
  848. std::string member_title;
  849. LLUUID insignia_id;
  850. LLUUID owner_role;
  851. U32 membership_fee = 0;
  852. BOOL open_enrollment = FALSE;
  853. S32 num_group_members = 0;
  854. S32 num_group_roles = 0;
  855. BOOL allow_publish = FALSE;
  856. BOOL mature = FALSE;
  857. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id );
  858. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_FounderID, founder_id);
  859. msg->getStringFast(_PREHASH_GroupData, _PREHASH_Name, name );
  860. msg->getStringFast(_PREHASH_GroupData, _PREHASH_Charter, charter );
  861. msg->getBOOLFast(_PREHASH_GroupData, _PREHASH_ShowInList, show_in_list );
  862. msg->getStringFast(_PREHASH_GroupData, _PREHASH_MemberTitle, member_title );
  863. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_InsigniaID, insignia_id );
  864. msg->getU64Fast(_PREHASH_GroupData, _PREHASH_PowersMask, powers_mask );
  865. msg->getU32Fast(_PREHASH_GroupData, _PREHASH_MembershipFee, membership_fee );
  866. msg->getBOOLFast(_PREHASH_GroupData, _PREHASH_OpenEnrollment, open_enrollment );
  867. msg->getS32Fast(_PREHASH_GroupData, _PREHASH_GroupMembershipCount, num_group_members);
  868. msg->getS32(_PREHASH_GroupData, "GroupRolesCount", num_group_roles);
  869. msg->getS32Fast(_PREHASH_GroupData, _PREHASH_Money, money);
  870. msg->getBOOL("GroupData", "AllowPublish", allow_publish);
  871. msg->getBOOL("GroupData", "MaturePublish", mature);
  872. msg->getUUID(_PREHASH_GroupData, "OwnerRole", owner_role);
  873. LLGroupMgrGroupData* group_datap = LLGroupMgr::getInstance()->createGroupData(group_id);
  874. group_datap->mName = name;
  875. group_datap->mCharter = charter;
  876. group_datap->mShowInList = show_in_list;
  877. group_datap->mInsigniaID = insignia_id;
  878. group_datap->mFounderID = founder_id;
  879. group_datap->mMembershipFee = membership_fee;
  880. group_datap->mOpenEnrollment = open_enrollment;
  881. group_datap->mAllowPublish = allow_publish;
  882. group_datap->mMaturePublish = mature;
  883. group_datap->mOwnerRole = owner_role;
  884. group_datap->mMemberCount = num_group_members;
  885. group_datap->mRoleCount = num_group_roles + 1; // Add the everyone role.
  886. group_datap->mGroupPropertiesDataComplete = TRUE;
  887. group_datap->mChanged = TRUE;
  888. LLGroupMgr::getInstance()->notifyObservers(GC_PROPERTIES);
  889. }
  890. // static
  891. void LLGroupMgr::processGroupRoleDataReply(LLMessageSystem* msg, void** data)
  892. {
  893. lldebugs << "LLGroupMgr::processGroupRoleDataReply" << llendl;
  894. LLUUID agent_id;
  895. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
  896. if (gAgent.getID() != agent_id)
  897. {
  898. llwarns << "Got group role data reply for another agent!" << llendl;
  899. return;
  900. }
  901. LLUUID group_id;
  902. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id );
  903. LLUUID request_id;
  904. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_RequestID, request_id);
  905. LLGroupMgrGroupData* group_datap = LLGroupMgr::getInstance()->getGroupData(group_id);
  906. if (!group_datap || (group_datap->mRoleDataRequestID != request_id))
  907. {
  908. llwarns << "processGroupPropertiesReply: Received incorrect (stale?) group or request id" << llendl;
  909. return;
  910. }
  911. msg->getS32(_PREHASH_GroupData, "RoleCount", group_datap->mRoleCount );
  912. std::string name;
  913. std::string title;
  914. std::string desc;
  915. U64 powers = 0;
  916. U32 member_count = 0;
  917. LLUUID role_id;
  918. U32 num_blocks = msg->getNumberOfBlocks("RoleData");
  919. U32 i = 0;
  920. for (i=0; i< num_blocks; ++i)
  921. {
  922. msg->getUUID("RoleData", "RoleID", role_id, i );
  923. msg->getString("RoleData","Name",name,i);
  924. msg->getString("RoleData","Title",title,i);
  925. msg->getString("RoleData","Description",desc,i);
  926. msg->getU64("RoleData","Powers",powers,i);
  927. msg->getU32("RoleData","Members",member_count,i);
  928. //there are 3 predifined roles - Owners, Officers, Everyone
  929. //there names are defined in lldatagroups.cpp
  930. //lets change names from server to localized strings
  931. if(name == "Everyone")
  932. {
  933. name = LLTrans::getString("group_role_everyone");
  934. }
  935. else if(name == "Officers")
  936. {
  937. name = LLTrans::getString("group_role_officers");
  938. }
  939. else if(name == "Owners")
  940. {
  941. name = LLTrans::getString("group_role_owners");
  942. }
  943. lldebugs << "Adding role data: " << name << " {" << role_id << "}" << llendl;
  944. LLGroupRoleData* rd = new LLGroupRoleData(role_id,name,title,desc,powers,member_count);
  945. group_datap->mRoles[role_id] = rd;
  946. }
  947. if (group_datap->mRoles.size() == (U32)group_datap->mRoleCount)
  948. {
  949. group_datap->mRoleDataComplete = TRUE;
  950. group_datap->mRoleDataRequestID.setNull();
  951. // We don't want to make role-member data requests until we have all the role data
  952. if (group_datap->mPendingRoleMemberRequest)
  953. {
  954. group_datap->mPendingRoleMemberRequest = FALSE;
  955. LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(group_datap->mID);
  956. }
  957. }
  958. group_datap->mChanged = TRUE;
  959. LLGroupMgr::getInstance()->notifyObservers(GC_ROLE_DATA);
  960. }
  961. // static
  962. void LLGroupMgr::processGroupRoleMembersReply(LLMessageSystem* msg, void** data)
  963. {
  964. lldebugs << "LLGroupMgr::processGroupRoleMembersReply" << llendl;
  965. LLUUID agent_id;
  966. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
  967. if (gAgent.getID() != agent_id)
  968. {
  969. llwarns << "Got group role members reply for another agent!" << llendl;
  970. return;
  971. }
  972. LLUUID request_id;
  973. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_RequestID, request_id);
  974. LLUUID group_id;
  975. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_GroupID, group_id );
  976. U32 total_pairs;
  977. msg->getU32(_PREHASH_AgentData, "TotalPairs", total_pairs);
  978. LLGroupMgrGroupData* group_datap = LLGroupMgr::getInstance()->getGroupData(group_id);
  979. if (!group_datap || (group_datap->mRoleMembersRequestID != request_id))
  980. {
  981. llwarns << "processGroupRoleMembersReply: Received incorrect (stale?) group or request id" << llendl;
  982. return;
  983. }
  984. U32 num_blocks = msg->getNumberOfBlocks("MemberData");
  985. U32 i;
  986. LLUUID member_id;
  987. LLUUID role_id;
  988. LLGroupRoleData* rd = NULL;
  989. LLGroupMemberData* md = NULL;
  990. LLGroupMgrGroupData::role_list_t::iterator ri;
  991. LLGroupMgrGroupData::member_list_t::iterator mi;
  992. // If total_pairs == 0, there are no members in any custom roles.
  993. if (total_pairs > 0)
  994. {
  995. for (i = 0;i < num_blocks; ++i)
  996. {
  997. msg->getUUID("MemberData","RoleID",role_id,i);
  998. msg->getUUID("MemberData","MemberID",member_id,i);
  999. if (role_id.notNull() && member_id.notNull() )
  1000. {
  1001. rd = NULL;
  1002. ri = group_datap->mRoles.find(role_id);
  1003. if (ri != group_datap->mRoles.end())
  1004. {
  1005. rd = ri->second;
  1006. }
  1007. md = NULL;
  1008. mi = group_datap->mMembers.find(member_id);
  1009. if (mi != group_datap->mMembers.end())
  1010. {
  1011. md = mi->second;
  1012. }
  1013. if (rd && md)
  1014. {
  1015. lldebugs << "Adding role-member pair: " << role_id << ", " << member_id << llendl;
  1016. rd->addMember(member_id);
  1017. md->addRole(role_id,rd);
  1018. }
  1019. else
  1020. {
  1021. if (!rd) llwarns << "Received role data for unknown role " << role_id << " in group " << group_id << llendl;
  1022. if (!md) llwarns << "Received role data for unknown member " << member_id << " in group " << group_id << llendl;
  1023. }
  1024. }
  1025. }
  1026. group_datap->mReceivedRoleMemberPairs += num_blocks;
  1027. }
  1028. if (group_datap->mReceivedRoleMemberPairs == total_pairs)
  1029. {
  1030. // Add role data for the 'everyone' role to all members
  1031. LLGroupRoleData* everyone = group_datap->mRoles[LLUUID::null];
  1032. if (!everyone)
  1033. {
  1034. llwarns << "Everyone role not found!" << llendl;
  1035. }
  1036. else
  1037. {
  1038. for (LLGroupMgrGroupData::member_list_t::iterator mi = group_datap->mMembers.begin();
  1039. mi != group_datap->mMembers.end(); ++mi)
  1040. {
  1041. LLGroupMemberData* data = mi->second;
  1042. if (data)
  1043. {
  1044. data->addRole(LLUUID::null,everyone);
  1045. }
  1046. }
  1047. }
  1048. group_datap->mRoleMemberDataComplete = TRUE;
  1049. group_datap->mRoleMembersRequestID.setNull();
  1050. }
  1051. group_datap->mChanged = TRUE;
  1052. LLGroupMgr::getInstance()->notifyObservers(GC_ROLE_MEMBER_DATA);
  1053. }
  1054. // static
  1055. void LLGroupMgr::processGroupTitlesReply(LLMessageSystem* msg, void** data)
  1056. {
  1057. lldebugs << "LLGroupMgr::processGroupTitlesReply" << llendl;
  1058. LLUUID agent_id;
  1059. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
  1060. if (gAgent.getID() != agent_id)
  1061. {
  1062. llwarns << "Got group properties reply for another agent!" << llendl;
  1063. return;
  1064. }
  1065. LLUUID group_id;
  1066. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_GroupID, group_id );
  1067. LLUUID request_id;
  1068. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_RequestID, request_id);
  1069. LLGroupMgrGroupData* group_datap = LLGroupMgr::getInstance()->getGroupData(group_id);
  1070. if (!group_datap || (group_datap->mTitlesRequestID != request_id))
  1071. {
  1072. llwarns << "processGroupTitlesReply: Received incorrect (stale?) group" << llendl;
  1073. return;
  1074. }
  1075. LLGroupTitle title;
  1076. S32 i = 0;
  1077. S32 blocks = msg->getNumberOfBlocksFast(_PREHASH_GroupData);
  1078. for (i=0; i<blocks; ++i)
  1079. {
  1080. msg->getString("GroupData","Title",title.mTitle,i);
  1081. msg->getUUID("GroupData","RoleID",title.mRoleID,i);
  1082. msg->getBOOL("GroupData","Selected",title.mSelected,i);
  1083. if (!title.mTitle.empty())
  1084. {
  1085. lldebugs << "LLGroupMgr adding title: " << title.mTitle << ", " << title.mRoleID << ", " << (title.mSelected ? 'Y' : 'N') << llendl;
  1086. group_datap->mTitles.push_back(title);
  1087. }
  1088. }
  1089. group_datap->mChanged = TRUE;
  1090. LLGroupMgr::getInstance()->notifyObservers(GC_TITLES);
  1091. }
  1092. // static
  1093. void LLGroupMgr::processEjectGroupMemberReply(LLMessageSystem* msg, void ** data)
  1094. {
  1095. lldebugs << "processEjectGroupMemberReply" << llendl;
  1096. LLUUID group_id;
  1097. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id);
  1098. BOOL success;
  1099. msg->getBOOLFast(_PREHASH_EjectData, _PREHASH_Success, success);
  1100. // If we had a failure, the group panel needs to be updated.
  1101. if (!success)
  1102. {
  1103. LLGroupActions::refresh(group_id);
  1104. }
  1105. }
  1106. // static
  1107. void LLGroupMgr::processJoinGroupReply(LLMessageSystem* msg, void ** data)
  1108. {
  1109. lldebugs << "processJoinGroupReply" << llendl;
  1110. LLUUID group_id;
  1111. BOOL success;
  1112. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id);
  1113. msg->getBOOLFast(_PREHASH_GroupData, _PREHASH_Success, success);
  1114. if (success)
  1115. {
  1116. // refresh all group information
  1117. gAgent.sendAgentDataUpdateRequest();
  1118. LLGroupMgr::getInstance()->clearGroupData(group_id);
  1119. // refresh the floater for this group, if any.
  1120. LLGroupActions::refresh(group_id);
  1121. }
  1122. }
  1123. // static
  1124. void LLGroupMgr::processLeaveGroupReply(LLMessageSystem* msg, void ** data)
  1125. {
  1126. lldebugs << "processLeaveGroupReply" << llendl;
  1127. LLUUID group_id;
  1128. BOOL success;
  1129. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id);
  1130. msg->getBOOLFast(_PREHASH_GroupData, _PREHASH_Success, success);
  1131. if (success)
  1132. {
  1133. // refresh all group information
  1134. gAgent.sendAgentDataUpdateRequest();
  1135. LLGroupMgr::getInstance()->clearGroupData(group_id);
  1136. // close the floater for this group, if any.
  1137. LLGroupActions::closeGroup(group_id);
  1138. }
  1139. }
  1140. // static
  1141. void LLGroupMgr::processCreateGroupReply(LLMessageSystem* msg, void ** data)
  1142. {
  1143. LLUUID group_id;
  1144. BOOL success;
  1145. std::string message;
  1146. msg->getUUIDFast(_PREHASH_ReplyData, _PREHASH_GroupID, group_id );
  1147. msg->getBOOLFast(_PREHASH_ReplyData, _PREHASH_Success, success );
  1148. msg->getStringFast(_PREHASH_ReplyData, _PREHASH_Message, message );
  1149. if (success)
  1150. {
  1151. // refresh all group information
  1152. gAgent.sendAgentDataUpdateRequest();
  1153. // HACK! We haven't gotten the agent group update yet, so ... um ... fake it.
  1154. // This is so when we go to modify the group we will be able to do so.
  1155. // This isn't actually too bad because real data will come down in 2 or 3 miliseconds and replace this.
  1156. LLGroupData gd;
  1157. gd.mAcceptNotices = TRUE;
  1158. gd.mListInProfile = TRUE;
  1159. gd.mContribution = 0;
  1160. gd.mID = group_id;
  1161. gd.mName = "new group";
  1162. gd.mPowers = GP_ALL_POWERS;
  1163. gAgent.mGroups.push_back(gd);
  1164. LLPanelGroup::refreshCreatedGroup(group_id);
  1165. //FIXME
  1166. //LLFloaterGroupInfo::closeCreateGroup();
  1167. //LLFloaterGroupInfo::showFromUUID(group_id,"roles_tab");
  1168. }
  1169. else
  1170. {
  1171. // *TODO: Translate
  1172. LLSD args;
  1173. args["MESSAGE"] = message;
  1174. LLNotificationsUtil::add("UnableToCreateGroup", args);
  1175. }
  1176. }
  1177. LLGroupMgrGroupData* LLGroupMgr::createGroupData(const LLUUID& id)
  1178. {
  1179. LLGroupMgrGroupData* group_datap;
  1180. group_map_t::iterator existing_group = LLGroupMgr::getInstance()->mGroups.find(id);
  1181. if (existing_group == LLGroupMgr::getInstance()->mGroups.end())
  1182. {
  1183. group_datap = new LLGroupMgrGroupData(id);
  1184. LLGroupMgr::getInstance()->addGroup(group_datap);
  1185. }
  1186. else
  1187. {
  1188. group_datap = existing_group->second;
  1189. }
  1190. return group_datap;
  1191. }
  1192. void LLGroupMgr::notifyObservers(LLGroupChange gc)
  1193. {
  1194. for (group_map_t::iterator gi = mGroups.begin(); gi != mGroups.end(); ++gi)
  1195. {
  1196. LLUUID group_id = gi->first;
  1197. if (gi->second->mChanged)
  1198. {
  1199. // notify LLGroupMgrObserver
  1200. // Copy the map because observers may remove themselves on update
  1201. observer_multimap_t observers = mObservers;
  1202. // find all observers for this group id
  1203. observer_multimap_t::iterator oi = observers.lower_bound(group_id);
  1204. observer_multimap_t::iterator end = observers.upper_bound(group_id);
  1205. for (; oi != end; ++oi)
  1206. {
  1207. oi->second->changed(gc);
  1208. }
  1209. gi->second->mChanged = FALSE;
  1210. // notify LLParticularGroupObserver
  1211. observer_map_t::iterator obs_it = mParticularObservers.find(group_id);
  1212. if(obs_it == mParticularObservers.end())
  1213. return;
  1214. observer_set_t& obs = obs_it->second;
  1215. for (observer_set_t::iterator ob_it = obs.begin(); ob_it != obs.end(); ++ob_it)
  1216. {
  1217. (*ob_it)->changed(group_id, gc);
  1218. }
  1219. }
  1220. }
  1221. }
  1222. void LLGroupMgr::addGroup(LLGroupMgrGroupData* group_datap)
  1223. {
  1224. if (mGroups.size() > MAX_CACHED_GROUPS)
  1225. {
  1226. // get rid of groups that aren't observed
  1227. for (group_map_t::iterator gi = mGroups.begin(); gi != mGroups.end() && mGroups.size() > MAX_CACHED_GROUPS / 2; )
  1228. {
  1229. observer_multimap_t::iterator oi = mObservers.find(gi->first);
  1230. if (oi == mObservers.end())
  1231. {
  1232. // not observed
  1233. LLGroupMgrGroupData* unobserved_groupp = gi->second;
  1234. delete unobserved_groupp;
  1235. mGroups.erase(gi++);
  1236. }
  1237. else
  1238. {
  1239. ++gi;
  1240. }
  1241. }
  1242. }
  1243. mGroups[group_datap->getID()] = group_datap;
  1244. }
  1245. void LLGroupMgr::sendGroupPropertiesRequest(const LLUUID& group_id)
  1246. {
  1247. lldebugs << "LLGroupMgr::sendGroupPropertiesRequest" << llendl;
  1248. // This will happen when we get the reply
  1249. //LLGroupMgrGroupData* group_datap = createGroupData(group_id);
  1250. LLMessageSystem* msg = gMessageSystem;
  1251. msg->newMessage("GroupProfileRequest");
  1252. msg->nextBlock("AgentData");
  1253. msg->addUUID("AgentID",gAgent.getID());
  1254. msg->addUUID("SessionID",gAgent.getSessionID());
  1255. msg->nextBlock("GroupData");
  1256. msg->addUUID("GroupID",group_id);
  1257. gAgent.sendReliableMessage();
  1258. }
  1259. void LLGroupMgr::sendGroupMembersRequest(const LLUUID& group_id)
  1260. {
  1261. lldebugs << "LLGroupMgr::sendGroupMembersRequest" << llendl;
  1262. LLGroupMgrGroupData* group_datap = createGroupData(group_id);
  1263. if (group_datap->mMemberRequestID.isNull())
  1264. {
  1265. group_datap->removeMemberData();
  1266. group_datap->mMemberRequestID.generate();
  1267. LLMessageSystem* msg = gMessageSystem;
  1268. msg->newMessage("GroupMembersRequest");
  1269. msg->nextBlock("AgentData");
  1270. msg->addUUID("AgentID",gAgent.getID());
  1271. msg->addUUID("SessionID",gAgent.getSessionID());
  1272. msg->nextBlock("GroupData");
  1273. msg->addUUID("GroupID",group_id);
  1274. msg->addUUID("RequestID",group_datap->mMemberRequestID);
  1275. gAgent.sendReliableMessage();
  1276. }
  1277. }
  1278. void LLGroupMgr::sendGroupRoleDataRequest(const LLUUID& group_id)
  1279. {
  1280. lldebugs << "LLGroupMgr::sendGroupRoleDataRequest" << llendl;
  1281. LLGroupMgrGroupData* group_datap = createGroupData(group_id);
  1282. if (group_datap->mRoleDataRequestID.isNull())
  1283. {
  1284. group_datap->removeRoleData();
  1285. group_datap->mRoleDataRequestID.generate();
  1286. LLMessageSystem* msg = gMessageSystem;
  1287. msg->newMessage("GroupRoleDataRequest");
  1288. msg->nextBlock("AgentData");
  1289. msg->addUUID("AgentID",gAgent.getID());
  1290. msg->addUUID("SessionID",gAgent.getSessionID());
  1291. msg->nextBlock("GroupData");
  1292. msg->addUUID("GroupID",group_id);
  1293. msg->addUUID("RequestID",group_datap->mRoleDataRequestID);
  1294. gAgent.sendReliableMessage();
  1295. }
  1296. }
  1297. void LLGroupMgr::sendGroupRoleMembersRequest(const LLUUID& group_id)
  1298. {
  1299. lldebugs << "LLGroupMgr::sendGroupRoleMembersRequest" << llendl;
  1300. LLGroupMgrGroupData* group_datap = createGroupData(group_id);
  1301. if (group_datap->mRoleMembersRequestID.isNull())
  1302. {
  1303. // Don't send the request if we don't have all the member or role data
  1304. if (!group_datap->isMemberDataComplete()
  1305. || !group_datap->isRoleDataComplete())
  1306. {
  1307. // *TODO: KLW FIXME: Should we start a member or role data request?
  1308. llinfos << " Pending: " << (group_datap->mPendingRoleMemberRequest ? "Y" : "N")
  1309. << " MemberDataComplete: " << (group_datap->mMemberDataComplete ? "Y" : "N")
  1310. << " RoleDataComplete: " << (group_datap->mRoleDataComplete ? "Y" : "N") << llendl;
  1311. group_datap->mPendingRoleMemberRequest = TRUE;
  1312. return;
  1313. }
  1314. group_datap->removeRoleMemberData();
  1315. group_datap->mRoleMembersRequestID.generate();
  1316. LLMessageSystem* msg = gMessageSystem;
  1317. msg->newMessage("GroupRoleMembersRequest");
  1318. msg->nextBlock("AgentData");
  1319. msg->addUUID("AgentID",gAgent.getID());
  1320. msg->addUUID("SessionID",gAgent.getSessionID());
  1321. msg->nextBlock("GroupData");
  1322. msg->addUUID("GroupID",group_id);
  1323. msg->addUUID("RequestID",group_datap->mRoleMembersRequestID);
  1324. gAgent.sendReliableMessage();
  1325. }
  1326. }
  1327. void LLGroupMgr::sendGroupTitlesRequest(const LLUUID& group_id)
  1328. {
  1329. lldebugs << "LLGroupMgr::sendGroupTitlesRequest" << llendl;
  1330. LLGroupMgrGroupData* group_datap = createGroupData(group_id);
  1331. group_datap->mTitles.clear();
  1332. group_datap->mTitlesRequestID.generate();
  1333. LLMessageSystem* msg = gMessageSystem;
  1334. msg->newMessage("GroupTitlesRequest");
  1335. msg->nextBlock("AgentData");
  1336. msg->addUUID("AgentID",gAgent.getID());
  1337. msg->addUUID("SessionID",gAgent.getSessionID());
  1338. msg->addUUID("GroupID",group_id);
  1339. msg->addUUID("RequestID",group_datap->mTitlesRequestID);
  1340. gAgent.sendReliableMessage();
  1341. }
  1342. void LLGroupMgr::sendGroupTitleUpdate(const LLUUID& group_id, const LLUUID& title_role_id)
  1343. {
  1344. lldebugs << "LLGroupMgr::sendGroupTitleUpdate" << llendl;
  1345. LLMessageSystem* msg = gMessageSystem;
  1346. msg->newMessage("GroupTitleUpdate");
  1347. msg->nextBlock("AgentData");
  1348. msg->addUUID("AgentID",gAgent.getID());
  1349. msg->addUUID("SessionID",gAgent.getSessionID());
  1350. msg->addUUID("GroupID",group_id);
  1351. msg->addUUID("TitleRoleID",title_role_id);
  1352. gAgent.sendReliableMessage();
  1353. // Save the change locally
  1354. LLGroupMgrGroupData* group_datap = createGroupData(group_id);
  1355. for (std::vector<LLGroupTitle>::iterator iter = group_datap->mTitles.begin();
  1356. iter != group_datap->mTitles.end(); ++iter)
  1357. {
  1358. if (iter->mRoleID == title_role_id)
  1359. {
  1360. iter->mSelected = TRUE;
  1361. }
  1362. else if (iter->mSelected)
  1363. {
  1364. iter->mSelected = FALSE;
  1365. }
  1366. }
  1367. }
  1368. // static
  1369. void LLGroupMgr::sendCreateGroupRequest(const std::string& name,
  1370. const std::string& charter,
  1371. U8 show_in_list,
  1372. const LLUUID& insignia,
  1373. S32 membership_fee,
  1374. BOOL open_enrollment,
  1375. BOOL allow_publish,
  1376. BOOL mature_publish)
  1377. {
  1378. LLMessageSystem* msg = gMessageSystem;
  1379. msg->newMessage("CreateGroupRequest");
  1380. msg->nextBlock("AgentData");
  1381. msg->addUUID("AgentID",gAgent.getID());
  1382. msg->addUUID("SessionID",gAgent.getSessionID());
  1383. msg->nextBlock("GroupData");
  1384. msg->addString("Name",name);
  1385. msg->addString("Charter",charter);
  1386. msg->addBOOL("ShowInList",show_in_list);
  1387. msg->addUUID("InsigniaID",insignia);
  1388. msg->addS32("MembershipFee",membership_fee);
  1389. msg->addBOOL("OpenEnrollment",open_enrollment);
  1390. msg->addBOOL("AllowPublish",allow_publish);
  1391. msg->addBOOL("MaturePublish",mature_publish);
  1392. gAgent.sendReliableMessage();
  1393. }
  1394. void LLGroupMgr::sendUpdateGroupInfo(const LLUUID& group_id)
  1395. {
  1396. lldebugs << "LLGroupMgr::sendUpdateGroupInfo" << llendl;
  1397. LLGroupMgrGroupData* group_datap = createGroupData(group_id);
  1398. LLMessageSystem* msg = gMessageSystem;
  1399. msg->newMessageFast(_PREHASH_UpdateGroupInfo);
  1400. msg->nextBlockFast(_PREHASH_AgentData);
  1401. msg->addUUIDFast(_PREHASH_AgentID,gAgent.getID());
  1402. msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID());
  1403. msg->nextBlockFast(_PREHASH_GroupData);
  1404. msg->addUUIDFast(_PREHASH_GroupID,group_datap->getID());
  1405. msg->addStringFast(_PREHASH_Charter,group_datap->mCharter);
  1406. msg->addBOOLFast(_PREHASH_ShowInList,group_datap->mShowInList);
  1407. msg->addUUIDFast(_PREHASH_InsigniaID,group_datap->mInsigniaID);
  1408. msg->addS32Fast(_PREHASH_MembershipFee,group_datap->mMembershipFee);
  1409. msg->addBOOLFast(_PREHASH_OpenEnrollment,group_datap->mOpenEnrollment);
  1410. msg->addBOOLFast(_PREHASH_AllowPublish,group_datap->mAllowPublish);
  1411. msg->addBOOLFast(_PREHASH_MaturePublish,group_datap->mMaturePublish);
  1412. gAgent.sendReliableMessage();
  1413. // Not expecting a response, so let anyone else watching know the data has changed.
  1414. group_datap->mChanged = TRUE;
  1415. notifyObservers(GC_PROPERTIES);
  1416. }
  1417. void LLGroupMgr::sendGroupRoleMemberChanges(const LLUUID& group_id)
  1418. {
  1419. lldebugs << "LLGroupMgr::sendGroupRoleMemberChanges" << llendl;
  1420. LLGroupMgrGroupData* group_datap = createGroupData(group_id);
  1421. if (group_datap->mRoleMemberChanges.empty()) return;
  1422. LLMessageSystem* msg = gMessageSystem;
  1423. bool start_message = true;
  1424. for (LLGroupMgrGroupData::change_map_t::const_iterator citer = group_datap->mRoleMemberChanges.begin();
  1425. citer != group_datap->mRoleMemberChanges.end(); ++citer)
  1426. {
  1427. if (start_message)
  1428. {
  1429. msg->newMessage("GroupRoleChanges");
  1430. msg->nextBlockFast(_PREHASH_AgentData);
  1431. msg->addUUIDFast(_PREHASH_AgentID,gAgent.getID());
  1432. msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID());
  1433. msg->addUUIDFast(_PREHASH_GroupID,group_id);
  1434. start_message = false;
  1435. }
  1436. msg->nextBlock("RoleChange");
  1437. msg->addUUID("RoleID",citer->second.mRole);
  1438. msg->addUUID("MemberID",citer->second.mMember);
  1439. msg->addU32("Change",(U32)citer->second.mChange);
  1440. if (msg->isSendFullFast())
  1441. {
  1442. gAgent.sendReliableMessage();
  1443. start_message = true;
  1444. }
  1445. }
  1446. if (!start_message)
  1447. {
  1448. gAgent.sendReliableMessage();
  1449. }
  1450. group_datap->mRoleMemberChanges.clear();
  1451. // Not expecting a response, so let anyone else watching know the data has changed.
  1452. group_datap->mChanged = TRUE;
  1453. notifyObservers(GC_ROLE_MEMBER_DATA);
  1454. }
  1455. //static
  1456. void LLGroupMgr::sendGroupMemberJoin(const LLUUID& group_id)
  1457. {
  1458. LLMessageSystem *msg = gMessageSystem;
  1459. msg->newMessageFast(_PREHASH_JoinGroupRequest);
  1460. msg->nextBlockFast(_PREHASH_AgentData);
  1461. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
  1462. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  1463. msg->nextBlockFast(_PREHASH_GroupData);
  1464. msg->addUUIDFast(_PREHASH_GroupID, group_id);
  1465. gAgent.sendReliableMessage();
  1466. }
  1467. // member_role_pairs is <member_id,role_id>
  1468. // static
  1469. void LLGroupMgr::sendGroupMemberInvites(const LLUUID& group_id, std::map<LLUUID,LLUUID>& member_role_pairs)
  1470. {
  1471. bool start_message = true;
  1472. LLMessageSystem* msg = gMessageSystem;
  1473. for (std::map<LLUUID,LLUUID>::iterator it = member_role_pairs.begin();
  1474. it != member_role_pairs.end(); ++it)
  1475. {
  1476. if (start_message)
  1477. {
  1478. msg->newMessage("InviteGroupRequest");
  1479. msg->nextBlock("AgentData");
  1480. msg->addUUID("AgentID",gAgent.getID());
  1481. msg->addUUID("SessionID",gAgent.getSessionID());
  1482. msg->nextBlock("GroupData");
  1483. msg->addUUID("GroupID",group_id);
  1484. start_message = false;
  1485. }
  1486. msg->nextBlock("InviteData");
  1487. msg->addUUID("InviteeID",(*it).first);
  1488. msg->addUUID("RoleID",(*it).second);
  1489. if (msg->isSendFull())
  1490. {
  1491. gAgent.sendReliableMessage();
  1492. start_message = true;
  1493. }
  1494. }
  1495. if (!start_message)
  1496. {
  1497. gAgent.sendReliableMessage();
  1498. }
  1499. }
  1500. //static
  1501. void LLGroupMgr::sendGroupMemberEjects(const LLUUID& group_id,
  1502. uuid_vec_t& member_ids)
  1503. {
  1504. bool start_message = true;
  1505. LLMessageSystem* msg = gMessageSystem;
  1506. LLGroupMgrGroupData* group_datap = LLGroupMgr::getInstance()->getGroupData(group_id);
  1507. if (!group_datap) return;
  1508. for (uuid_vec_t::iterator it = member_ids.begin();
  1509. it != member_ids.end(); ++it)
  1510. {
  1511. LLUUID& ejected_member_id = (*it);
  1512. // Can't use 'eject' to leave a group.
  1513. if (ejected_member_id == gAgent.getID()) continue;
  1514. // Make sure they are in the group, and we need the member data
  1515. LLGroupMgrGroupData::member_list_t::iterator mit = group_datap->mMembers.find(ejected_member_id);
  1516. if (mit != group_datap->mMembers.end())
  1517. {
  1518. // Add them to the message
  1519. if (start_message)
  1520. {
  1521. msg->newMessage("EjectGroupMemberRequest");
  1522. msg->nextBlock("AgentData");
  1523. msg->addUUID("AgentID",gAgent.getID());
  1524. msg->addUUID("SessionID",gAgent.getSessionID());
  1525. msg->nextBlock("GroupData");
  1526. msg->addUUID("GroupID",group_id);
  1527. start_message = false;
  1528. }
  1529. msg->nextBlock("EjectData");
  1530. msg->addUUID("EjecteeID",ejected_member_id);
  1531. if (msg->isSendFull())
  1532. {
  1533. gAgent.sendReliableMessage();
  1534. start_message = true;
  1535. }
  1536. LLGroupMemberData* member_data = (*mit).second;
  1537. // Clean up groupmgr
  1538. for (LLGroupMemberData::role_list_t::iterator rit = member_data->roleBegin();
  1539. rit != member_data->roleEnd(); ++rit)
  1540. {
  1541. if ((*rit).first.notNull() && (*rit).second!=0)
  1542. {
  1543. (*rit).second->removeMember(ejected_member_id);
  1544. }
  1545. }
  1546. group_datap->mMembers.erase(ejected_member_id);
  1547. // member_data was introduced and is used here instead of (*mit).second to avoid crash because of invalid iterator
  1548. // It becomes invalid after line with erase above. EXT-4778
  1549. delete member_data;
  1550. }
  1551. }
  1552. if (!start_message)
  1553. {
  1554. gAgent.sendReliableMessage();
  1555. }
  1556. }
  1557. void LLGroupMgr::sendGroupRoleChanges(const LLUUID& group_id)
  1558. {
  1559. lldebugs << "LLGroupMgr::sendGroupRoleChanges" << llendl;
  1560. LLGroupMgrGroupData* group_datap = getGroupData(group_id);
  1561. if (group_datap && group_datap->pendingRoleChanges())
  1562. {
  1563. group_datap->sendRoleChanges();
  1564. // Not expecting a response, so let anyone else watching know the data has changed.
  1565. group_datap->mChanged = TRUE;
  1566. notifyObservers(GC_ROLE_DATA);
  1567. }
  1568. }
  1569. void LLGroupMgr::cancelGroupRoleChanges(const LLUUID& group_id)
  1570. {
  1571. lldebugs << "LLGroupMgr::cancelGroupRoleChanges" << llendl;
  1572. LLGroupMgrGroupData* group_datap = getGroupData(group_id);
  1573. if (group_datap) group_datap->cancelRoleChanges();
  1574. }
  1575. //static
  1576. bool LLGroupMgr::parseRoleActions(const std::string& xml_filename)
  1577. {
  1578. LLXMLNodePtr root;
  1579. BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root);
  1580. if (!success || !root || !root->hasName( "role_actions" ))
  1581. {
  1582. llerrs << "Problem reading UI role_actions file: " << xml_filename << llendl;
  1583. return false;
  1584. }
  1585. LLXMLNodeList role_list;
  1586. root->getChildren("action_set", role_list, false);
  1587. for (LLXMLNodeList::iterator role_iter = role_list.begin(); role_iter != role_list.end(); ++role_iter)
  1588. {
  1589. LLXMLNodePtr action_set = role_iter->second;
  1590. LLRoleActionSet* role_action_set = new LLRoleActionSet();
  1591. LLRoleAction* role_action_data = new LLRoleAction();
  1592. // name=
  1593. std::string action_set_name;
  1594. if (action_set->getAttributeString("name", action_set_name))
  1595. {
  1596. lldebugs << "Loading action set " << action_set_name << llendl;
  1597. role_action_data->mName = action_set_name;
  1598. }
  1599. else
  1600. {
  1601. llwarns << "Unable to parse action set with no name" << llendl;
  1602. delete role_action_set;
  1603. delete role_action_data;
  1604. continue;
  1605. }
  1606. // description=
  1607. std::string set_description;
  1608. if (action_set->getAttributeString("description", set_description))
  1609. {
  1610. role_action_data->mDescription = set_description;
  1611. }
  1612. // long description=
  1613. std::string set_longdescription;
  1614. if (action_set->getAttributeString("longdescription", set_longdescription))
  1615. {
  1616. role_action_data->mLongDescription = set_longdescription;
  1617. }
  1618. // power mask=
  1619. U64 set_power_mask = 0;
  1620. LLXMLNodeList action_list;
  1621. LLXMLNodeList::iterator action_iter;
  1622. action_set->getChildren("action", action_list, false);
  1623. for (action_iter = action_list.begin(); action_iter != action_list.end(); ++action_iter)
  1624. {
  1625. LLXMLNodePtr action = action_iter->second;
  1626. LLRoleAction* role_action = new LLRoleAction();
  1627. // name=
  1628. std::string action_name;
  1629. if (action->getAttributeString("name", action_name))
  1630. {
  1631. lldebugs << "Loading action " << action_name << llendl;
  1632. role_action->mName = action_name;
  1633. }
  1634. else
  1635. {
  1636. llwarns << "Unable to parse action with no name" << llendl;
  1637. delete role_action;
  1638. continue;
  1639. }
  1640. // description=
  1641. std::string description;
  1642. if (action->getAttributeString("description", description))
  1643. {
  1644. role_action->mDescription = description;
  1645. }
  1646. // long description=
  1647. std::string longdescription;
  1648. if (action->getAttributeString("longdescription", longdescription))
  1649. {
  1650. role_action->mLongDescription = longdescription;
  1651. }
  1652. // description=
  1653. S32 power_bit = 0;
  1654. if (action->getAttributeS32("value", power_bit))
  1655. {
  1656. if (0 <= power_bit && power_bit < 64)
  1657. {
  1658. role_action->mPowerBit = 0x1LL << power_bit;
  1659. }
  1660. }
  1661. set_power_mask |= role_action->mPowerBit;
  1662. role_action_set->mActions.push_back(role_action);
  1663. }
  1664. role_action_data->mPowerBit = set_power_mask;
  1665. role_action_set->mActionSetData = role_action_data;
  1666. LLGroupMgr::getInstance()->mRoleActionSets.push_back(role_action_set);
  1667. }
  1668. return true;
  1669. }
  1670. // static
  1671. void LLGroupMgr::debugClearAllGroups(void*)
  1672. {
  1673. LLGroupMgr::getInstance()->clearGroups();
  1674. LLGroupMgr::parseRoleActions("role_actions.xml");
  1675. }