aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llfloaterbulkpermission.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llfloaterbulkpermission.cpp595
1 files changed, 595 insertions, 0 deletions
diff --git a/linden/indra/newview/llfloaterbulkpermission.cpp b/linden/indra/newview/llfloaterbulkpermission.cpp
new file mode 100644
index 0000000..29d94bc
--- /dev/null
+++ b/linden/indra/newview/llfloaterbulkpermission.cpp
@@ -0,0 +1,595 @@
1/**
2 * @file llfloaterbulkpermissions.cpp
3 * @brief A floater which allows task inventory item's properties to be changed on mass.
4 *
5 * $LicenseInfo:firstyear=2008&license=viewergpl$
6 *
7 * Copyright (c) 2008, 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 http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 *
22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above,
24 * and agree to abide by those obligations.
25 *
26 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
27 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
28 * COMPLETENESS OR PERFORMANCE.
29 * $/LicenseInfo$
30 */
31
32/* Allow multiple task inventory properties to be set in one go, by Michelle2 Zenovka */
33
34/* TODO
35
36 * Add in the option to select objects or task inventory
37s
38
39It would be nice to set the permissions on groups of prims as well as task inventory
40
41*/
42
43
44#include "llviewerprecompiledheaders.h"
45#include "llfloaterbulkpermission.h"
46#include "llagent.h"
47#include "llchat.h"
48#include "llviewerwindow.h"
49#include "llviewerobject.h"
50#include "llviewerobjectlist.h"
51#include "llviewerregion.h"
52#include "lscript_rt_interface.h"
53#include "llviewercontrol.h"
54#include "llviewerobject.h"
55#include "llviewerregion.h"
56#include "llresmgr.h"
57#include "llbutton.h"
58#include "lldir.h"
59#include "llfloaterchat.h"
60#include "llviewerstats.h"
61#include "lluictrlfactory.h"
62#include "llselectmgr.h"
63#include "llinventory.h"
64
65
66#include <algorithm>
67#include <functional>
68#include "llcachename.h"
69#include "lldbstrings.h"
70#include "llinventory.h"
71
72#include "llagent.h"
73#include "llbutton.h"
74#include "llcheckboxctrl.h"
75#include "llfloateravatarinfo.h"
76#include "llfloatergroupinfo.h"
77#include "llinventorymodel.h"
78#include "lllineeditor.h"
79#include "llradiogroup.h"
80#include "llresmgr.h"
81#include "roles_constants.h"
82#include "llselectmgr.h"
83#include "lltextbox.h"
84#include "lluiconstants.h"
85#include "llviewerinventory.h"
86#include "llviewerobjectlist.h"
87#include "llviewerregion.h"
88#include "llviewercontrol.h"
89
90#include "lluictrlfactory.h"
91
92
93const char* BULKPERM_QUEUE_TITLE = "Update Progress";
94const char* BULKPERM_START_STRING = "update";
95
96namespace
97{
98 struct BulkQueueObjects : public LLSelectedObjectFunctor
99 {
100 BOOL scripted;
101 BOOL modifiable;
102 LLFloaterBulkPermission* mQueue;
103 BulkQueueObjects(LLFloaterBulkPermission* q) : mQueue(q), scripted(FALSE), modifiable(FALSE) {}
104 virtual bool apply(LLViewerObject* obj)
105 {
106 scripted = obj->flagScripted();
107 modifiable = obj->permModify();
108
109 mQueue->addObject(obj->getID());
110 return false;
111
112 }
113 };
114}
115
116///----------------------------------------------------------------------------
117/// Class LLFloaterBulkPermission
118///----------------------------------------------------------------------------
119
120// static
121LLMap<LLUUID, LLFloaterBulkPermission*> LLFloaterBulkPermission::sInstances;
122
123
124// Default constructor
125LLFloaterBulkPermission::LLFloaterBulkPermission(const std::string& name,
126 const LLRect& rect,
127 const char* title,
128 const char* start_string) :
129 LLFloater(name, rect, title,
130 RESIZE_YES, DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT,
131 DRAG_ON_TOP, MINIMIZE_YES, CLOSE_YES)
132{
133
134 req_perm_mask=0; // This should match the default state the checkboxes are set to
135 recurse=false;
136
137 LLUICtrlFactory::getInstance()->buildFloater(this,"floater_bulk_perms.xml");
138
139 childSetAction("Apply...",onApplyBtn,this);
140 childSetEnabled("Apply...",TRUE);
141
142 childSetCommitCallback("Modify",&onCommitPermissions, this);
143 childSetCommitCallback("Trans",&onCommitPermissions, this);
144 childSetCommitCallback("Copy",&onCommitPermissions, this);
145
146 //childSetCommitCallback("Recurse",&onRecurse, this);
147
148 childSetCommitCallback("Parent",&onParent, this);
149
150 childSetCommitCallback("objects",&InvSelection, this);
151 childSetCommitCallback("scripts",&InvSelection, this);
152 childSetCommitCallback("textures",&InvSelection, this);
153 childSetCommitCallback("sounds",&InvSelection, this);
154 childSetCommitCallback("animations",&InvSelection, this);
155 childSetCommitCallback("notecards",&InvSelection, this);
156 childSetCommitCallback("landmarks",&InvSelection, this);
157 childSetCommitCallback("bodyparts",&InvSelection, this);
158 childSetCommitCallback("clothing",&InvSelection, this);
159 childSetCommitCallback("gestures",&InvSelection, this);
160
161 //Set variable state to XUI default state consistancy
162 processObject=getChild<LLCheckBoxCtrl>("objects")->get();
163 processScript=getChild<LLCheckBoxCtrl>("scripts")->get();
164 processTexture=getChild<LLCheckBoxCtrl>("textures")->get();
165 processSound=getChild<LLCheckBoxCtrl>("sounds")->get();
166 processAnimation=getChild<LLCheckBoxCtrl>("animations")->get();
167 processNotecard=getChild<LLCheckBoxCtrl>("notecards")->get();
168 processGesture=getChild<LLCheckBoxCtrl>("gestures")->get();
169 processClothing=getChild<LLCheckBoxCtrl>("clothing")->get();
170 processBodypart=getChild<LLCheckBoxCtrl>("bodyparts")->get();
171 processLandmark=getChild<LLCheckBoxCtrl>("landmarks")->get();
172 parent=getChild<LLCheckBoxCtrl>("Parent")->get();
173
174
175 setTitle(title);
176
177 if (!getHost())
178 {
179 LLRect curRect = getRect();
180 translate(rect.mLeft - curRect.mLeft, rect.mTop - curRect.mTop);
181 }
182
183 mStartString = start_string;
184 mDone = FALSE;
185 sInstances.addData(mID, this);
186
187}
188
189void LLFloaterBulkPermission::doApply()
190{
191 // Its alive now do the nasty work that the ScriptQueue and friends try to do in the menu code
192 // but first grab the user options
193
194 LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
195 list->deleteAllItems();
196
197 //Apply to selected objects if requested first
198
199 if(parent)
200 {
201 llinfos<< "Setting permission on parent items" << llendl;
202 LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_NEXT_OWNER,true, req_perm_mask);
203 LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_NEXT_OWNER,false, ~req_perm_mask); //How annoying need to set and unset
204 }
205
206
207 LLFloaterBulkPermission* q;
208 q=(LLFloaterBulkPermission*)this;
209
210 BulkQueueObjects func(q);
211 const bool firstonly = false;
212 bool fail = LLSelectMgr::getInstance()->getSelection()->applyToObjects(&func, firstonly);
213 if(fail)
214 {
215 if ( !func.modifiable )
216 {
217 gViewerWindow->alertXml("NO MODIFY");
218 }
219 else
220 {
221 llwarns << "Bad logic. Are there actualy any items in that prim?" << llendl;
222 }
223 }
224 else
225 {
226 if (!q->start())
227 {
228 llwarns << "Unexpected failure attepmting to set permissions." << llendl;
229 }
230 }
231}
232
233// Destroys the object
234LLFloaterBulkPermission::~LLFloaterBulkPermission()
235{
236 sInstances.removeData(mID);
237}
238
239// find an instance by ID. Return NULL if it does not exist.
240// static
241LLFloaterBulkPermission* LLFloaterBulkPermission::findInstance(const LLUUID& id)
242{
243 if(sInstances.checkData(id))
244 {
245 return sInstances.getData(id);
246 }
247 return NULL;
248}
249
250
251// This is the callback method for the viewer object currently being
252// worked on.
253// NOT static, virtual!
254void LLFloaterBulkPermission::inventoryChanged(LLViewerObject* viewer_object,
255 InventoryObjectList* inv,
256 S32,
257 void* q_id)
258{
259 llinfos << "LLFloaterBulkPermission::inventoryChanged() for object "
260 << viewer_object->getID() << llendl;
261
262 //Remove this listener from the object since its
263 //listener callback is now being executed.
264
265 //We remove the listener here because the function
266 //removeVOInventoryListener removes the listener from a ViewerObject
267 //which it internally stores.
268
269 //If we call this further down in the function, calls to handleInventory
270 //and nextObject may update the interally stored viewer object causing
271 //the removal of the incorrect listener from an incorrect object.
272
273 //Fixes SL-6119:Recompile scripts fails to complete
274 removeVOInventoryListener();
275
276 if (viewer_object && inv && (viewer_object->getID() == mCurrentObjectID) )
277 {
278 handleInventory(viewer_object, inv);
279 }
280 else
281 {
282 // something went wrong...
283 // note that we're not working on this one, and move onto the
284 // next object in the list.
285 llwarns << "No inventory for " << mCurrentObjectID
286 << llendl;
287 nextObject();
288 }
289}
290
291void LLFloaterBulkPermission::onApplyBtn(void* user_data)
292{
293 LLFloaterBulkPermission* self = (LLFloaterBulkPermission*)user_data;
294 self->doApply();
295}
296
297
298// static
299void LLFloaterBulkPermission::InvSelection(LLUICtrl* ctrl, void* data)
300{
301 LLFloaterBulkPermission* self = (LLFloaterBulkPermission*)data;
302
303 self->processObject=self->getChild<LLCheckBoxCtrl>("objects")->get();
304 self->processScript=self->getChild<LLCheckBoxCtrl>("scripts")->get();
305 self->processTexture=self->getChild<LLCheckBoxCtrl>("textures")->get();
306 self->processSound=self->getChild<LLCheckBoxCtrl>("sounds")->get();
307 self->processAnimation=self->getChild<LLCheckBoxCtrl>("animations")->get();
308 self->processNotecard=self->getChild<LLCheckBoxCtrl>("notecards")->get();
309 self->processGesture=self->getChild<LLCheckBoxCtrl>("gestures")->get();
310 self->processClothing=self->getChild<LLCheckBoxCtrl>("clothing")->get();
311 self->processBodypart=self->getChild<LLCheckBoxCtrl>("bodyparts")->get();
312 self->processLandmark=self->getChild<LLCheckBoxCtrl>("landmarks")->get();
313
314
315}
316
317// static
318void LLFloaterBulkPermission::onParent(LLUICtrl* ctrl, void* data)
319{
320 LLFloaterBulkPermission* self = (LLFloaterBulkPermission*)data;
321 self->parent=self->getChild<LLCheckBoxCtrl>("Parent")->get();
322}
323
324// static
325void LLFloaterBulkPermission::onRecurse(LLUICtrl* ctrl, void* data)
326{
327 LLFloaterBulkPermission* self = (LLFloaterBulkPermission*)data;
328 self->recurse=self->getChild<LLCheckBoxCtrl>("Recurse")->get();
329}
330
331// static
332void LLFloaterBulkPermission::onCommitPermissions(LLUICtrl* ctrl, void* data)
333{
334 LLFloaterBulkPermission* self = (LLFloaterBulkPermission*)data;
335 LLCheckBoxCtrl* CheckModify = self->getChild<LLCheckBoxCtrl>("Modify");
336 LLCheckBoxCtrl* CheckCopy = self->getChild<LLCheckBoxCtrl>("Copy");
337 LLCheckBoxCtrl* CheckTrans = self->getChild<LLCheckBoxCtrl>("Trans");
338
339 self->req_perm_mask=0;
340
341 if(CheckModify->get())
342 {
343 self->req_perm_mask|=PERM_MODIFY;
344 }
345 else
346 {
347 self->req_perm_mask&=~PERM_MODIFY;
348 }
349
350 if(CheckCopy->get())
351 {
352 self->req_perm_mask|=PERM_COPY;
353 }
354 else
355 {
356 self->req_perm_mask&=~PERM_COPY;
357 }
358
359 if(CheckTrans->get())
360 {
361 self->req_perm_mask|=PERM_TRANSFER;
362 }
363 else
364 {
365 self->req_perm_mask&=~PERM_TRANSFER;
366 }
367
368
369}
370
371void LLFloaterBulkPermission::addObject(const LLUUID& id)
372{
373 mObjectIDs.put(id);
374}
375
376BOOL LLFloaterBulkPermission::start()
377{
378 llinfos << "LLFloaterBulkPermission::start()" << llendl;
379 char buffer[MAX_STRING]; /*Flawfinder: ignore*/
380 snprintf(buffer, sizeof(buffer), "Starting %s of %d items.", mStartString, mObjectIDs.count()); /* Flawfinder: ignore */
381
382 LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
383 list->addCommentText(buffer);
384
385 return nextObject();
386}
387
388BOOL LLFloaterBulkPermission::isDone() const
389{
390 return (mCurrentObjectID.isNull() || (mObjectIDs.count() == 0));
391}
392
393// go to the next object. If no objects left, it falls out silently
394// and waits to be killed by the window being closed.
395BOOL LLFloaterBulkPermission::nextObject()
396{
397 S32 count;
398 BOOL successful_start = FALSE;
399 do
400 {
401 count = mObjectIDs.count();
402 llinfos << "LLFloaterBulkPermission::nextObject() - " << count
403 << " objects left to process." << llendl;
404 mCurrentObjectID.setNull();
405 if(count > 0)
406 {
407 successful_start = popNext();
408 }
409 llinfos << "LLFloaterBulkPermission::nextObject() "
410 << (successful_start ? "successful" : "unsuccessful")
411 << llendl;
412 } while((mObjectIDs.count() > 0) && !successful_start);
413
414 if(isDone() && !mDone)
415 {
416
417 LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
418 mDone = TRUE;
419 char buffer[MAX_STRING]; /*Flawfinder: ignore*/
420 snprintf(buffer, sizeof(buffer), "Done."); /* Flawfinder: ignore */
421 list->addCommentText(buffer);
422
423 }
424 return successful_start;
425}
426
427// returns true if the queue has started, otherwise false. This
428// method pops the top object off of the queue.
429BOOL LLFloaterBulkPermission::popNext()
430{
431 // get the first element off of the container, and attempt to get
432 // the inventory.
433 BOOL rv = FALSE;
434 S32 count = mObjectIDs.count();
435 if(mCurrentObjectID.isNull() && (count > 0))
436 {
437 mCurrentObjectID = mObjectIDs.get(0);
438 llinfos << "LLFloaterBulkPermission::popNext() - mCurrentID: "
439 << mCurrentObjectID << llendl;
440 mObjectIDs.remove(0);
441 LLViewerObject* obj = gObjectList.findObject(mCurrentObjectID);
442 if(obj)
443 {
444 llinfos << "LLFloaterBulkPermission::popNext() requesting inv for "
445 << mCurrentObjectID << llendl;
446 LLUUID* id = new LLUUID(mID);
447
448 registerVOInventoryListener(obj,id);
449 requestVOInventory();
450 rv = TRUE;
451 }
452 else
453 {
454 llinfos<<"LLFloaterBulkPermission::popNext() returned a NULL LLViewerObject" <<llendl;
455 //Arrrg what do we do here?
456 }
457 }
458
459 return rv;
460}
461
462
463// static
464LLFloaterBulkPermission* LLFloaterBulkPermission::create()
465{
466 S32 left, top;
467 gFloaterView->getNewFloaterPosition(&left, &top);
468 LLRect rect = gSavedSettings.getRect("CompileOutputRect");
469 rect.translate(left - rect.mLeft, top - rect.mTop);
470 LLFloaterBulkPermission* new_queue = new LLFloaterBulkPermission("queue",rect,"Setting Bulk permissions","Results");
471 new_queue->open(); /*Flawfinder: ignore*/
472 return new_queue;
473}
474
475
476void LLFloaterBulkPermission::handleInventory(LLViewerObject* viewer_obj, InventoryObjectList* inv)
477{
478 // find all of the lsl, leaving off duplicates. We'll remove
479 // all matching asset uuids on compilation success.
480
481 llinfos<<"handleInventory"<<llendl;
482
483 char buffer[MAX_STRING]; /*Flawfinder: ignore*/
484 LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
485
486 InventoryObjectList::const_iterator it = inv->begin();
487 InventoryObjectList::const_iterator end = inv->end();
488 for ( ; it != end; ++it)
489 {
490 llinfos<<"Doing iterator of inventory"<<llendl;
491
492 if( ( (*it)->getType() == LLAssetType::AT_LSL_TEXT && processScript) ||
493 ( (*it)->getType() == LLAssetType::AT_TEXTURE && processTexture) ||
494 ( (*it)->getType() == LLAssetType::AT_SOUND && processSound) ||
495 ( (*it)->getType() == LLAssetType::AT_LANDMARK && processLandmark) ||
496 ( (*it)->getType() == LLAssetType::AT_CLOTHING && processClothing) ||
497 ( (*it)->getType() == LLAssetType::AT_OBJECT && processObject) ||
498 ( (*it)->getType() == LLAssetType::AT_NOTECARD && processNotecard) ||
499 ( (*it)->getType() == LLAssetType::AT_BODYPART && processBodypart) ||
500 ( (*it)->getType() == LLAssetType::AT_ANIMATION && processAnimation) ||
501 ( (*it)->getType() == LLAssetType::AT_GESTURE && processGesture))
502 {
503
504 LLViewerObject* object = gObjectList.findObject(viewer_obj->getID());
505
506 if (object)
507 {
508 LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it));
509 LLViewerInventoryItem* new_item = (LLViewerInventoryItem*)item;
510 LLPermissions perm(new_item->getPermissions());
511
512 // chomp the inventory name so it fits in the scroll window nicely
513 // and the user can see the [OK]
514 std::string invname;
515 invname=item->getName().substr(0,item->getName().size() < 30 ? item->getName().size() : 30 );
516
517 // My attempt at checking valid permissions, CHECK ME
518 // note its not actually bad to try to set permissions that are not allowed as the
519 // server will protect against this, but it will piss the user off if its wrong
520 if(
521 (perm.getCreator()==gAgentID) ||
522 (perm.getMaskOwner() & PERM_TRANSFER) && (perm.getMaskOwner() & PERM_MODIFY) ||
523 (gAgent.getGroupID()==perm.getGroup() && (perm.getMaskGroup() & PERM_TRANSFER) && (perm.getMaskGroup() & PERM_MODIFY))
524 ){
525 llinfos<<"Setting perms"<<llendl;
526 perm.setMaskNext(req_perm_mask);
527 new_item->setPermissions(perm);
528 updateInventory(object,new_item,TASK_INVENTORY_ITEM_KEY,FALSE);
529 snprintf(buffer, sizeof(buffer), "Setting perms on '%s' [OK]", invname.c_str()); /* Flawfinder: ignore */
530 }
531 else
532 {
533 llinfos<<"NOT setting perms"<<llendl;
534 snprintf(buffer, sizeof(buffer), "Setting perms on '%s' [FAILED]", invname.c_str()); /* Flawfinder: ignore */
535
536 }
537
538 list->addCommentText(buffer);
539
540 if(recurse && ( (*it)->getType() == LLAssetType::AT_OBJECT && processObject))
541 {
542 //Add this object back to the queue to be processed as it has inventory
543 snprintf(buffer, sizeof(buffer), "Queueing object '%s' for open", invname.c_str());
544 llwarns << "Queueing object "<< invname.c_str() << " ID "<< (*it)->getUUID()<<llendl;
545 mObjectIDs.put((*it)->getUUID());
546 // This will not YET work. as this is not a viewer object the unpack will fail
547 }
548
549 }
550 }
551 }
552
553 nextObject();
554}
555
556
557// Avoid inventory callbacks etc by just fire and forgetting the message with the permissions update
558// we could do this via LLViewerObject::updateInventory but that uses inventory call backs and buggers
559// us up and we would have a dodgy item iterator
560
561void LLFloaterBulkPermission::updateInventory(
562 LLViewerObject* object,
563 LLViewerInventoryItem* item,
564 U8 key,
565 bool is_new)
566{
567 LLMemType mt(LLMemType::MTYPE_OBJECT);
568
569
570 // This slices the object into what we're concerned about on the
571 // viewer. The simulator will take the permissions and transfer
572 // ownership.
573 LLPointer<LLViewerInventoryItem> task_item =
574 new LLViewerInventoryItem(item->getUUID(), mID, item->getPermissions(),
575 item->getAssetUUID(), item->getType(),
576 item->getInventoryType(),
577 item->getName(), item->getDescription(),
578 item->getSaleInfo(),
579 item->getFlags(),
580 item->getCreationDate());
581 task_item->setTransactionID(item->getTransactionID());
582 LLMessageSystem* msg = gMessageSystem;
583 msg->newMessageFast(_PREHASH_UpdateTaskInventory);
584 msg->nextBlockFast(_PREHASH_AgentData);
585 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
586 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
587 msg->nextBlockFast(_PREHASH_UpdateData);
588 msg->addU32Fast(_PREHASH_LocalID, object->mLocalID);
589 msg->addU8Fast(_PREHASH_Key, key);
590 msg->nextBlockFast(_PREHASH_InventoryData);
591 task_item->packMessage(msg);
592 msg->sendReliable(object->getRegion()->getHost());
593
594}
595