llfloaterbulkpermission.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. /**
  2. * @file llfloaterbulkpermissions.cpp
  3. * @author Michelle2 Zenovka
  4. * @brief A floater which allows task inventory item's properties to be changed on mass.
  5. *
  6. * $LicenseInfo:firstyear=2008&license=viewergpl$
  7. *
  8. * Copyright (c) 2008-2009, Linden Research, Inc.
  9. *
  10. * Second Life Viewer Source Code
  11. * The source code in this file ("Source Code") is provided by Linden Lab
  12. * to you under the terms of the GNU General Public License, version 2.0
  13. * ("GPL"), unless you have obtained a separate licensing agreement
  14. * ("Other License"), formally executed by you and Linden Lab. Terms of
  15. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  16. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  17. *
  18. * There are special exceptions to the terms and conditions of the GPL as
  19. * it is applied to this Source Code. View the full text of the exception
  20. * in the file doc/FLOSS-exception.txt in this software distribution, or
  21. * online at
  22. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  23. *
  24. * By copying, modifying or distributing this software, you acknowledge
  25. * that you have read and understood your obligations described above,
  26. * and agree to abide by those obligations.
  27. *
  28. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  29. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  30. * COMPLETENESS OR PERFORMANCE.
  31. * $/LicenseInfo$
  32. */
  33. #include "llviewerprecompiledheaders.h"
  34. #include "llfloaterbulkpermission.h"
  35. #include "lldir.h"
  36. #include "llscrolllistctrl.h"
  37. #include "lluictrlfactory.h"
  38. #include "llagent.h"
  39. #include "llfloaterperms.h" // For utilities
  40. #include "llselectmgr.h"
  41. #include "llviewercontrol.h"
  42. #include "llviewerobjectlist.h"
  43. #include "llviewerregion.h"
  44. #include "roles_constants.h" // For GP_OBJECT_MANIPULATE
  45. LLFloaterBulkPermission::LLFloaterBulkPermission(const LLSD& seed)
  46. : mDone(false)
  47. {
  48. mID.generate();
  49. LLUICtrlFactory::getInstance()->buildFloater(this,
  50. "floater_bulk_perms.xml");
  51. childSetEnabled("next_owner_transfer",
  52. gSavedSettings.getBool("BulkChangeNextOwnerCopy"));
  53. if (!gAgent.hasInventoryMaterial())
  54. {
  55. gSavedSettings.setBool("BulkChangeIncludeMaterials", false);
  56. childSetEnabled("check_material", false);
  57. std::string tooltip = getString("no_material_cap");
  58. childSetToolTip("icon_material", tooltip);
  59. childSetToolTip("check_material", tooltip);
  60. }
  61. childSetAction("help", onHelpBtn, this);
  62. childSetAction("apply", onApplyBtn, this);
  63. childSetAction("close", onCloseBtn, this);
  64. childSetAction("check_all", onCheckAll, this);
  65. childSetAction("check_none", onUncheckAll, this);
  66. childSetCommitCallback("next_owner_copy", &onCommitCopy, this);
  67. }
  68. void LLFloaterBulkPermission::doApply()
  69. {
  70. // Inspects a stream of selected object contents and adds modifiable ones
  71. // to the given array.
  72. class ModifiableGatherer final : public LLSelectedNodeFunctor
  73. {
  74. public:
  75. ModifiableGatherer(uuid_vec_t& q)
  76. : mQueue(q)
  77. {
  78. }
  79. bool apply(LLSelectNode* node) override
  80. {
  81. if (node->allowOperationOnNode(PERM_MODIFY, GP_OBJECT_MANIPULATE))
  82. {
  83. mQueue.emplace_back(node->getObject()->getID());
  84. }
  85. return true;
  86. }
  87. private:
  88. uuid_vec_t& mQueue;
  89. };
  90. LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
  91. list->deleteAllItems();
  92. ModifiableGatherer gatherer(mObjectIDs);
  93. gSelectMgr.getSelection()->applyToNodes(&gatherer);
  94. if (mObjectIDs.empty())
  95. {
  96. list->addCommentText(getString("nothing_to_modify_text"));
  97. }
  98. else
  99. {
  100. mDone = false;
  101. if (!start())
  102. {
  103. llwarns << "Unexpected bulk permission change failure." << llendl;
  104. }
  105. }
  106. }
  107. // This is the callback method for the viewer object currently being worked on.
  108. //virtual
  109. void LLFloaterBulkPermission::inventoryChanged(LLViewerObject* viewer_object,
  110. LLInventoryObject::object_list_t* inv,
  111. S32, void* q_id)
  112. {
  113. // Remove this listener from the object since its listener callback is now
  114. // being executed.
  115. // We remove the listener here because the removeVOInventoryListener()
  116. // method removes the listener from a LLViewerObject which it internally
  117. // stores.
  118. // If we call this further down in the method, calls to handleInventory and
  119. // nextObject may update the interally stored viewer object causing the
  120. // removal of the incorrect listener from an incorrect object.
  121. // Fixes SL-6119: recompile scripts fails to complete
  122. removeVOInventoryListener();
  123. if (viewer_object && inv && (viewer_object->getID() == mCurrentObjectID))
  124. {
  125. handleInventory(viewer_object, inv);
  126. }
  127. else
  128. {
  129. // Something went wrong... Note that we are not working on this one,
  130. // and move onto the next object in the list.
  131. llwarns << "No inventory for " << mCurrentObjectID << llendl;
  132. nextObject();
  133. }
  134. }
  135. void LLFloaterBulkPermission::onApplyBtn(void* user_data)
  136. {
  137. LLFloaterBulkPermission* self = (LLFloaterBulkPermission*)user_data;
  138. self->doApply();
  139. }
  140. void LLFloaterBulkPermission::onHelpBtn(void* user_data)
  141. {
  142. gNotifications.add("HelpBulkPermission");
  143. }
  144. void LLFloaterBulkPermission::onCloseBtn(void* user_data)
  145. {
  146. LLFloaterBulkPermission* self = (LLFloaterBulkPermission*)user_data;
  147. self->onClose(false);
  148. }
  149. //static
  150. void LLFloaterBulkPermission::onCommitCopy(LLUICtrl* ctrl, void* user_data)
  151. {
  152. LLFloaterBulkPermission* self = (LLFloaterBulkPermission*)user_data;
  153. // Implements fair use
  154. bool copyable = gSavedSettings.getBool("BulkChangeNextOwnerCopy");
  155. if (!copyable)
  156. {
  157. gSavedSettings.setBool("BulkChangeNextOwnerTransfer", true);
  158. }
  159. LLCheckBoxCtrl* xfer = self->getChild<LLCheckBoxCtrl>("next_owner_transfer");
  160. xfer->setEnabled(copyable);
  161. }
  162. bool LLFloaterBulkPermission::start()
  163. {
  164. // Note: number of top-level objects to modify is mObjectIDs.size().
  165. getChild<LLScrollListCtrl>("queue output")->addCommentText(getString("start_text"));
  166. return nextObject();
  167. }
  168. // Go to the next object and start if found. Returns false if no objects left,
  169. // true otherwise.
  170. bool LLFloaterBulkPermission::nextObject()
  171. {
  172. bool successful_start = false;
  173. do
  174. {
  175. S32 count = mObjectIDs.size();
  176. mCurrentObjectID.setNull();
  177. if (count > 0)
  178. {
  179. successful_start = popNext();
  180. }
  181. }
  182. while (mObjectIDs.size() > 0 && !successful_start);
  183. if (isDone() && !mDone)
  184. {
  185. getChild<LLScrollListCtrl>("queue output")->addCommentText(getString("done_text"));
  186. mDone = true;
  187. }
  188. return successful_start;
  189. }
  190. // Pops the top object off of the queue. Returns true if the queue has started,
  191. // otherwise false.
  192. bool LLFloaterBulkPermission::popNext()
  193. {
  194. // Get the head element from the container, and attempt to get its
  195. // inventory.
  196. bool rv = false;
  197. S32 count = mObjectIDs.size();
  198. if (mCurrentObjectID.isNull() && count > 0)
  199. {
  200. mCurrentObjectID = mObjectIDs[0];
  201. mObjectIDs.erase(mObjectIDs.begin());
  202. LLViewerObject* obj = gObjectList.findObject(mCurrentObjectID);
  203. if (obj)
  204. {
  205. LLUUID* id = new LLUUID(mID);
  206. registerVOInventoryListener(obj, id);
  207. requestVOInventory();
  208. rv = true;
  209. }
  210. else
  211. {
  212. llwarns << "NULL LLViewerObject" <<llendl;
  213. }
  214. }
  215. return rv;
  216. }
  217. //static
  218. void LLFloaterBulkPermission::setAllChecked(bool check)
  219. {
  220. gSavedSettings.setBool("BulkChangeIncludeAnimations", check);
  221. gSavedSettings.setBool("BulkChangeIncludeBodyParts", check);
  222. gSavedSettings.setBool("BulkChangeIncludeClothing", check);
  223. gSavedSettings.setBool("BulkChangeIncludeGestures", check);
  224. gSavedSettings.setBool("BulkChangeIncludeLandmarks", check);
  225. bool has_cap = gAgent.hasInventoryMaterial();
  226. gSavedSettings.setBool("BulkChangeIncludeMaterials", check && has_cap);
  227. gSavedSettings.setBool("BulkChangeIncludeNotecards", check);
  228. gSavedSettings.setBool("BulkChangeIncludeObjects", check);
  229. gSavedSettings.setBool("BulkChangeIncludeScripts", check);
  230. gSavedSettings.setBool("BulkChangeIncludeSettings", check);
  231. gSavedSettings.setBool("BulkChangeIncludeSounds", check);
  232. gSavedSettings.setBool("BulkChangeIncludeTextures", check);
  233. }
  234. void LLFloaterBulkPermission::handleInventory(LLViewerObject* viewer_obj,
  235. LLInventoryObject::object_list_t* inv)
  236. {
  237. LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
  238. LLInventoryObject::object_list_t::const_iterator it = inv->begin();
  239. LLInventoryObject::object_list_t::const_iterator end = inv->end();
  240. for (; it != end; ++it)
  241. {
  242. LLAssetType::EType asstype = (*it)->getType();
  243. if ((asstype == LLAssetType::AT_ANIMATION &&
  244. gSavedSettings.getBool("BulkChangeIncludeAnimations")) ||
  245. (asstype == LLAssetType::AT_BODYPART &&
  246. gSavedSettings.getBool("BulkChangeIncludeBodyParts")) ||
  247. (asstype == LLAssetType::AT_CLOTHING &&
  248. gSavedSettings.getBool("BulkChangeIncludeClothing")) ||
  249. (asstype == LLAssetType::AT_GESTURE &&
  250. gSavedSettings.getBool("BulkChangeIncludeGestures")) ||
  251. (asstype == LLAssetType::AT_LANDMARK &&
  252. gSavedSettings.getBool("BulkChangeIncludeLandmarks")) ||
  253. (asstype == LLAssetType::AT_MATERIAL &&
  254. gSavedSettings.getBool("BulkChangeIncludeMaterials")) ||
  255. (asstype == LLAssetType::AT_NOTECARD &&
  256. gSavedSettings.getBool("BulkChangeIncludeNotecards")) ||
  257. (asstype == LLAssetType::AT_OBJECT &&
  258. gSavedSettings.getBool("BulkChangeIncludeObjects")) ||
  259. (asstype == LLAssetType::AT_LSL_TEXT &&
  260. gSavedSettings.getBool("BulkChangeIncludeScripts")) ||
  261. (asstype == LLAssetType::AT_SOUND &&
  262. gSavedSettings.getBool("BulkChangeIncludeSounds")) ||
  263. (asstype == LLAssetType::AT_SETTINGS &&
  264. gSavedSettings.getBool("BulkChangeIncludeSettings")) ||
  265. (asstype == LLAssetType::AT_TEXTURE &&
  266. gSavedSettings.getBool("BulkChangeIncludeTextures")))
  267. {
  268. LLViewerObject* object = gObjectList.findObject(viewer_obj->getID());
  269. if (object)
  270. {
  271. LLInventoryItem* item =
  272. (LLInventoryItem*)((LLInventoryObject*)(*it));
  273. LLViewerInventoryItem* new_item = (LLViewerInventoryItem*)item;
  274. LLPermissions perm(new_item->getPermissions());
  275. U32 flags = new_item->getFlags();
  276. U32 desired_next_owner_perms =
  277. LLFloaterPerms::getNextOwnerPerms("BulkChange");
  278. if (asstype == LLAssetType::AT_SETTINGS)
  279. {
  280. desired_next_owner_perms |= PERM_COPY;
  281. }
  282. U32 desired_everyone_perms =
  283. LLFloaterPerms::getEveryonePerms("BulkChange");
  284. U32 desired_group_perms =
  285. LLFloaterPerms::getGroupPerms("BulkChange");
  286. // If next owner permissions have changed (and this is an object)
  287. // then set the slam permissions flag so that they are applied on rez.
  288. if ((perm.getMaskNextOwner() != desired_next_owner_perms)
  289. && (new_item->getType() == LLAssetType::AT_OBJECT))
  290. {
  291. flags |= LLInventoryItem::II_FLAGS_OBJECT_SLAM_PERM;
  292. }
  293. // If everyone permissions have changed (and this is an object)
  294. // then set the overwrite everyone permissions flag so they
  295. // are applied on rez.
  296. if ((perm.getMaskEveryone() != desired_everyone_perms)
  297. && (new_item->getType() == LLAssetType::AT_OBJECT))
  298. {
  299. flags |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE;
  300. }
  301. // If group permissions have changed (and this is an object)
  302. // then set the overwrite group permissions flag so they
  303. // are applied on rez.
  304. if ((perm.getMaskGroup() != desired_group_perms)
  305. && (new_item->getType() == LLAssetType::AT_OBJECT))
  306. {
  307. flags |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP;
  308. }
  309. // Chomp the inventory name so it fits in the scroll window
  310. // nicely and the user can see the [OK]
  311. std::string invname = item->getName();
  312. if (invname.size() > 30)
  313. {
  314. invname = invname.substr(0, 30);
  315. }
  316. LLUIString status_text = getString("status_text");
  317. status_text.setArg("[NAME]", invname.c_str());
  318. // Check whether we appear to have the appropriate permissions
  319. // to change permission on this item. Although the server will
  320. // disallow any forbidden changes, it is a good idea to guess
  321. // correctly so that we can warn the user. The risk of getting
  322. // this check wrong is therefore the possibility of incorrectly
  323. // choosing to not attempt to make a valid change.
  324. #if 0 // Trouble is this is extremely difficult to do and even when
  325. // we know the results it is difficult to design the best
  326. // messaging. Therefore in this initial implementation we will
  327. // always try to set the requested permissions and consider all
  328. // cases successful and perhaps later try to implement a
  329. // smarter, friendlier solution. -MG
  330. // for group and everyone masks
  331. if (!gAgent.allowOperation(PERM_MODIFY, perm, GP_OBJECT_MANIPULATE))
  332. // && something else // for next owner perms
  333. {
  334. //status_text.setArg("[STATUS]", getString("status_bad_text"));
  335. status_text.setArg("[STATUS]", "");
  336. }
  337. else
  338. #endif
  339. {
  340. perm.setMaskNext(desired_next_owner_perms);
  341. perm.setMaskEveryone(desired_everyone_perms);
  342. perm.setMaskGroup(desired_group_perms);
  343. new_item->setPermissions(perm); // here's the beef
  344. new_item->setFlags(flags); // and the tofu
  345. updateInventory(object, new_item);
  346. //status_text.setArg("[STATUS]", getString("status_ok_text"));
  347. status_text.setArg("[STATUS]", "");
  348. }
  349. list->addCommentText(status_text.getString());
  350. #if 0 // *TODO if we are an object inside an object we should check a
  351. // recuse flag and if set open the inventory of the object and
  352. // recurse - Michelle2 Zenovka
  353. if (recurse && processObject &&
  354. (*it)->getType() == LLAssetType::AT_OBJECT)
  355. {
  356. // I think we need to get the UUID of the object inside the
  357. // inventory call item->fetchFromServer(); we need a
  358. // callback to say item has arrived *sigh* we then need to
  359. // do something like:
  360. // LLUUID* id = new LLUUID(mID);
  361. // registerVOInventoryListener(obj, id);
  362. // requestVOInventory();
  363. }
  364. #endif
  365. }
  366. }
  367. }
  368. nextObject();
  369. }
  370. // Avoid inventory callbacks etc by just fire and forgetting the message with
  371. // the permissions update we could do this via LLViewerObject::updateInventory
  372. // but that uses inventory call backs and buggers us up and we would have a
  373. // dodgy item iterator
  374. void LLFloaterBulkPermission::updateInventory(LLViewerObject* object,
  375. LLViewerInventoryItem* item)
  376. {
  377. // This slices the object into what we're concerned about on the viewer.
  378. // The simulator will take the permissions and transfer ownership.
  379. LLPointer<LLViewerInventoryItem> task_item =
  380. new LLViewerInventoryItem(item->getUUID(), mID, item->getPermissions(),
  381. item->getAssetUUID(), item->getType(),
  382. item->getInventoryType(), item->getName(),
  383. item->getDescription(), item->getSaleInfo(),
  384. item->getFlags(), item->getCreationDate());
  385. task_item->setTransactionID(item->getTransactionID());
  386. LLMessageSystem* msg = gMessageSystemp;
  387. msg->newMessageFast(_PREHASH_UpdateTaskInventory);
  388. msg->nextBlockFast(_PREHASH_AgentData);
  389. msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
  390. msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
  391. msg->nextBlockFast(_PREHASH_UpdateData);
  392. msg->addU32Fast(_PREHASH_LocalID, object->mLocalID);
  393. msg->addU8Fast(_PREHASH_Key, TASK_INVENTORY_ITEM_KEY);
  394. msg->nextBlockFast(_PREHASH_InventoryData);
  395. task_item->packMessage(msg);
  396. msg->sendReliable(object->getRegion()->getHost());
  397. }