aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llfloaterreporter.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llfloaterreporter.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/llfloaterreporter.cpp')
-rw-r--r--linden/indra/newview/llfloaterreporter.cpp916
1 files changed, 916 insertions, 0 deletions
diff --git a/linden/indra/newview/llfloaterreporter.cpp b/linden/indra/newview/llfloaterreporter.cpp
new file mode 100644
index 0000000..116b338
--- /dev/null
+++ b/linden/indra/newview/llfloaterreporter.cpp
@@ -0,0 +1,916 @@
1/**
2 * @file llfloaterreporter.cpp
3 * @brief Bug and abuse reports.
4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "llviewerprecompiledheaders.h"
29
30#include <sstream>
31
32// self include
33#include "llfloaterreporter.h"
34
35// linden library includes
36#include "llassetstorage.h"
37#include "llcachename.h"
38#include "llfontgl.h"
39#include "llgl.h" // for renderer
40#include "llinventory.h"
41#include "llstring.h"
42#include "llsys.h"
43#include "llversion.h"
44#include "message.h"
45#include "v3math.h"
46
47// viewer project includes
48#include "llagent.h"
49#include "llbutton.h"
50#include "llcheckboxctrl.h"
51#include "llinventoryview.h"
52#include "lllineeditor.h"
53#include "lltexturectrl.h"
54#include "llscrolllistctrl.h"
55#include "llimview.h"
56#include "lltextbox.h"
57#include "lldispatcher.h"
58#include "llviewertexteditor.h"
59#include "llviewerobject.h"
60#include "llviewerregion.h"
61#include "llcombobox.h"
62#include "llfloaterrate.h"
63#include "lltooldraganddrop.h"
64#include "llfloatermap.h"
65#include "lluiconstants.h"
66#include "llcallingcard.h"
67#include "llviewerobjectlist.h"
68#include "llagent.h"
69#include "lltoolobjpicker.h"
70#include "lltoolmgr.h"
71#include "llviewermenu.h" // for LLResourceData
72#include "llviewerwindow.h"
73#include "llviewerimagelist.h"
74#include "llworldmap.h"
75#include "llfilepicker.h"
76#include "llfloateravatarpicker.h"
77#include "lldir.h"
78#include "llselectmgr.h"
79#include "llviewerbuild.h"
80#include "llvieweruictrlfactory.h"
81#include "viewer.h"
82
83
84const U32 INCLUDE_SCREENSHOT = 0x01 << 0;
85
86//-----------------------------------------------------------------------------
87// Globals
88//-----------------------------------------------------------------------------
89
90// this map keeps track of current reporter instances
91// there can only be one instance of each reporter type
92LLMap< EReportType, LLFloaterReporter* > gReporterInstances;
93
94// keeps track of where email is going to - global to avoid a pile
95// of static/non-static access outside my control
96namespace {
97 static BOOL gEmailToEstateOwner = FALSE;
98 static BOOL gDialogVisible = FALSE;
99}
100
101//-----------------------------------------------------------------------------
102// Member functions
103//-----------------------------------------------------------------------------
104LLFloaterReporter::LLFloaterReporter(
105 const std::string& name,
106 const LLRect& rect,
107 const std::string& title,
108 EReportType report_type)
109 :
110 LLFloater(name, rect, title),
111 mReportType(report_type),
112 mObjectID(),
113 mScreenID(),
114 mAbuserID(),
115 mDeselectOnClose( FALSE ),
116 mPicking( FALSE),
117 mPosition(),
118 mCopyrightWarningSeen( FALSE )
119{
120 if (report_type == BUG_REPORT)
121 {
122 gUICtrlFactory->buildFloater(this, "floater_report_bug.xml");
123 }
124 else
125 {
126 gUICtrlFactory->buildFloater(this, "floater_report_abuse.xml");
127 }
128
129 LLViewerRegion *regionp = gAgent.getRegion();
130 if (regionp)
131 {
132 childSetText("sim_field", regionp->getName() );
133 childSetText("abuse_location_edit", regionp->getName() );
134 }
135
136 LLButton* pick_btn = LLUICtrlFactory::getButtonByName(this, "pick_btn");
137 if (pick_btn)
138 {
139 // XUI: Why aren't these in viewerart.ini?
140 pick_btn->setImages( "UIImgFaceUUID",
141 "UIImgFaceSelectedUUID" );
142 childSetAction("pick_btn", onClickObjPicker, this);
143 }
144
145 if (report_type != BUG_REPORT)
146 {
147 // abuser name is selected from a list
148 LLLineEditor* le = (LLLineEditor*)getCtrlByNameAndType("abuser_name_edit", WIDGET_TYPE_LINE_EDITOR);
149 le->setEnabled( FALSE );
150 }
151
152 childSetAction("select_abuser", onClickSelectAbuser, this);
153
154 childSetAction("send_btn", onClickSend, this);
155 childSetAction("cancel_btn", onClickCancel, this);
156
157 enableControls(TRUE);
158
159 // convert the position to a string
160 LLVector3d pos = gAgent.getPositionGlobal();
161 if (regionp)
162 {
163 pos -= regionp->getOriginGlobal();
164 }
165 setPosBox(pos);
166
167 gReporterInstances.addData(report_type, this);
168
169 // Upload a screenshot, but don't draw this floater.
170 setVisible(FALSE);
171 uploadScreenshot();
172 setVisible(TRUE);
173
174 // Default text to be blank
175 childSetText("object_name", "");
176 childSetText("owner_name", "");
177
178 childSetFocus("summary_edit");
179
180 mDefaultSummary = childGetText("details_edit");
181
182 gDialogVisible = TRUE;
183
184 // only request details for abuse reports (not BUG reports)
185 if (report_type != BUG_REPORT)
186 {
187 // send a message and ask for information about this region -
188 // result comes back in processRegionInfo(..)
189 LLMessageSystem* msg = gMessageSystem;
190 msg->newMessage("RequestRegionInfo");
191 msg->nextBlock("AgentData");
192 msg->addUUID("AgentID", gAgent.getID());
193 msg->addUUID("SessionID", gAgent.getSessionID());
194 gAgent.sendReliableMessage();
195 };
196}
197
198// static
199void LLFloaterReporter::processRegionInfo(LLMessageSystem* msg)
200{
201 U32 region_flags;
202 msg->getU32("RegionInfo", "RegionFlags", region_flags);
203 gEmailToEstateOwner = ( region_flags & REGION_FLAGS_ABUSE_EMAIL_TO_ESTATE_OWNER );
204
205 if ( gDialogVisible )
206 {
207 if ( gEmailToEstateOwner )
208 {
209 gViewerWindow->alertXml("HelpReportAbuseEmailEO");
210 }
211 else
212 gViewerWindow->alertXml("HelpReportAbuseEmailLL");
213 };
214}
215
216// virtual
217LLFloaterReporter::~LLFloaterReporter()
218{
219 gReporterInstances.removeData(mReportType);
220 // child views automatically deleted
221 mObjectID = LLUUID::null;
222
223 if (mPicking)
224 {
225 closePickTool(this);
226 }
227
228 mPosition.setVec(0.0f, 0.0f, 0.0f);
229
230 std::for_each(mMCDList.begin(), mMCDList.end(), DeletePointer() );
231 mMCDList.clear();
232
233 if (gSelectMgr)
234 {
235 gSelectMgr->deselectTransient();
236 }
237
238 gDialogVisible = FALSE;
239}
240
241// virtual
242void LLFloaterReporter::draw()
243{
244 // this is set by a static callback sometime after the dialog is created.
245 // Only disable screenshot for abuse reports to estate owners - bug reports always
246 // allow screenshots to be taken.
247 if ( gEmailToEstateOwner && ( mReportType != BUG_REPORT ) )
248 {
249 childSetValue("screen_check", FALSE );
250 childSetEnabled("screen_check", FALSE );
251 }
252 else
253 {
254 childSetEnabled("screen_check", TRUE );
255 }
256
257 LLFloater::draw();
258}
259
260void LLFloaterReporter::enableControls(BOOL enable)
261{
262 childSetEnabled("category_combo", enable);
263 // bug reports never include the chat history
264 if (mReportType != BUG_REPORT)
265 {
266 childSetEnabled("chat_check", enable);
267 }
268 childSetEnabled("screen_check", enable);
269 childDisable("screenshot");
270 childSetEnabled("pick_btn", enable);
271 childSetEnabled("summary_edit", enable);
272 childSetEnabled("details_edit", enable);
273 childSetEnabled("send_btn", enable);
274 childSetEnabled("cancel_btn", enable);
275}
276
277void LLFloaterReporter::getObjectInfo(const LLUUID& object_id)
278{
279 // TODO --
280 // 1 need to send to correct simulator if object is not
281 // in same simulator as agent
282 // 2 display info in widget window that gives feedback that
283 // we have recorded the object info
284 // 3 can pick avatar ==> might want to indicate when a picked
285 // object is an avatar, attachment, or other category
286
287 mObjectID = object_id;
288
289 if (LLUUID::null != mObjectID)
290 {
291 // get object info for the user's benefit
292 LLViewerObject* objectp = NULL;
293 objectp = gObjectList.findObject( mObjectID );
294 if (objectp)
295 {
296 if ( objectp->isAttachment() )
297 {
298 objectp = (LLViewerObject*)objectp->getRoot();
299 }
300
301 // correct the region and position information
302 LLViewerRegion *regionp = objectp->getRegion();
303 if (regionp)
304 {
305 childSetText("sim_field", regionp->getName());
306 LLVector3d global_pos;
307 global_pos.setVec(objectp->getPositionRegion());
308 setPosBox(global_pos);
309 }
310
311 if (objectp->isAvatar())
312 {
313 // we have the information we need
314 LLString object_owner;
315
316 LLNameValue* firstname = objectp->getNVPair("FirstName");
317 LLNameValue* lastname = objectp->getNVPair("LastName");
318 if (firstname && lastname)
319 {
320 object_owner.append(firstname->getString());
321 object_owner.append(1, ' ');
322 object_owner.append(lastname->getString());
323 }
324 else
325 {
326 object_owner.append("Unknown");
327 }
328 childSetText("object_name", object_owner);
329 childSetText("owner_name", object_owner);
330 }
331 else
332 {
333 // we have to query the simulator for information
334 // about this object
335 LLMessageSystem* msg = gMessageSystem;
336 U32 request_flags = (mReportType == BUG_REPORT) ? BUG_REPORT_REQUEST : COMPLAINT_REPORT_REQUEST;
337 msg->newMessageFast(_PREHASH_RequestObjectPropertiesFamily);
338 msg->nextBlockFast(_PREHASH_AgentData);
339 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
340 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
341 msg->nextBlockFast(_PREHASH_ObjectData);
342 msg->addU32Fast(_PREHASH_RequestFlags, request_flags );
343 msg->addUUIDFast(_PREHASH_ObjectID, mObjectID);
344 LLViewerRegion* regionp = objectp->getRegion();
345 msg->sendReliable( regionp->getHost() );
346 }
347 }
348 }
349}
350
351
352// static
353void LLFloaterReporter::onClickSelectAbuser(void *userdata)
354{
355 LLFloaterReporter *self = (LLFloaterReporter *)userdata;
356
357 gFloaterView->getParentFloater(self)->addDependentFloater(LLFloaterAvatarPicker::show(callbackAvatarID, userdata, FALSE, TRUE ));
358}
359
360// static
361void LLFloaterReporter::callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data)
362{
363 LLFloaterReporter* self = (LLFloaterReporter*) data;
364
365 if (ids.empty() || names.empty()) return;
366
367 // this should never be called in a bug report but here for safety.
368 if ( self->mReportType != BUG_REPORT )
369 {
370 self->childSetText("abuser_name_edit", names[0] );
371
372 self->mAbuserID = ids[0];
373
374 self->refresh();
375 };
376}
377
378// static
379void LLFloaterReporter::onClickSend(void *userdata)
380{
381 LLFloaterReporter *self = (LLFloaterReporter *)userdata;
382
383 // only do this for abuse reports
384 if ( self->mReportType != BUG_REPORT )
385 {
386 if ( ! self->mCopyrightWarningSeen )
387 {
388 LLString details_lc = self->childGetText("details_edit");
389 LLString::toLower( details_lc );
390 LLString summary_lc = self->childGetText("summary_edit");
391 LLString::toLower( summary_lc );
392 if ( details_lc.find( "copyright" ) != std::string::npos ||
393 summary_lc.find( "copyright" ) != std::string::npos )
394 {
395 gViewerWindow->alertXml("HelpReportAbuseContainsCopyright");
396 self->mCopyrightWarningSeen = TRUE;
397 return;
398 };
399 };
400 };
401
402 if (self->mPicking)
403 {
404 closePickTool(self);
405 }
406 self->sendReport();
407}
408
409
410// static
411void LLFloaterReporter::onClickCancel(void *userdata)
412{
413 LLFloaterReporter *self = (LLFloaterReporter *)userdata;
414
415 // reset flag in case the next report also contains this text
416 self->mCopyrightWarningSeen = FALSE;
417
418 if (self->mPicking)
419 {
420 closePickTool(self);
421 }
422 self->close();
423}
424
425
426// static
427void LLFloaterReporter::onClickObjPicker(void *userdata)
428{
429 LLFloaterReporter *self = (LLFloaterReporter *)userdata;
430 gToolObjPicker->setExitCallback(LLFloaterReporter::closePickTool, self);
431 gToolMgr->setTransientTool(gToolObjPicker);
432 self->mPicking = TRUE;
433 self->childSetText("object_name", "");
434 self->childSetText("owner_name", "");
435 LLButton* pick_btn = LLUICtrlFactory::getButtonByName(self, "pick_btn");
436 if (pick_btn) pick_btn->setToggleState(TRUE);
437}
438
439
440// static
441void LLFloaterReporter::closePickTool(void *userdata)
442{
443 LLFloaterReporter *self = (LLFloaterReporter *)userdata;
444
445 LLUUID object_id = gToolObjPicker->getObjectID();
446 self->getObjectInfo(object_id);
447
448 gToolMgr->clearTransientTool();
449 self->mPicking = FALSE;
450 LLButton* pick_btn = LLUICtrlFactory::getButtonByName(self, "pick_btn");
451 if (pick_btn) pick_btn->setToggleState(FALSE);
452}
453
454
455// static
456void LLFloaterReporter::showFromMenu(EReportType report_type)
457{
458 if (gReporterInstances.checkData(report_type))
459 {
460 // ...bring that window to front
461 LLFloaterReporter *f = gReporterInstances.getData(report_type);
462 f->open();
463 }
464 else
465 {
466 LLFloaterReporter *f;
467 if (BUG_REPORT == report_type)
468 {
469 f = LLFloaterReporter::createNewBugReporter();
470 }
471 else if (COMPLAINT_REPORT == report_type)
472 {
473 f = LLFloaterReporter::createNewAbuseReporter();
474 }
475 else
476 {
477 llwarns << "Unknown LLViewerReporter type : " << report_type << llendl;
478 return;
479 }
480
481 f->center();
482
483 if (report_type == BUG_REPORT)
484 {
485 gViewerWindow->alertXml("HelpReportBug");
486 }
487 else
488 {
489 // popup for abuse reports is triggered elsewhere
490 }
491
492 // grab the user's name
493 LLString fullname;
494 gAgent.buildFullname(fullname);
495 f->childSetText("reporter_field", fullname);
496 }
497}
498
499
500// static
501void LLFloaterReporter::showFromObject(const LLUUID& object_id)
502{
503 LLFloaterReporter* f = createNewAbuseReporter();
504 f->center();
505 f->setFocus(TRUE);
506
507 // grab the user's name
508 LLString fullname;
509 gAgent.buildFullname(fullname);
510 f->childSetText("reporter_field", fullname);
511
512 // Request info for this object
513 f->getObjectInfo(object_id);
514
515 // Need to deselect on close
516 f->mDeselectOnClose = TRUE;
517
518 f->open();
519}
520
521
522// static
523LLFloaterReporter* LLFloaterReporter::getReporter(EReportType report_type)
524{
525 LLFloaterReporter *self = NULL;
526 if (gReporterInstances.checkData(report_type))
527 {
528 // ...bring that window to front
529 self = gReporterInstances.getData(report_type);
530 }
531 return self;
532}
533
534LLFloaterReporter* LLFloaterReporter::createNewAbuseReporter()
535{
536 return new LLFloaterReporter("complaint_reporter",
537 LLRect(),
538 "Report Abuse",
539 COMPLAINT_REPORT);
540}
541
542//static
543LLFloaterReporter* LLFloaterReporter::createNewBugReporter()
544{
545 return new LLFloaterReporter("bug_reporter",
546 LLRect(),
547 "Report Bug",
548 BUG_REPORT);
549}
550
551
552
553void LLFloaterReporter::setPickedObjectProperties(const char *object_name, const char *owner_name)
554{
555 childSetText("object_name", object_name);
556 childSetText("owner_name", owner_name);
557}
558
559void LLFloaterReporter::sendReport()
560{
561 LLViewerRegion *regionp = gAgent.getRegion();
562 if (!regionp) return;
563 // Ensure user selected a category from the list
564 LLSD category_sd = childGetValue("category_combo");
565 U8 category = (U8)category_sd.asInteger();
566 if (category == 0)
567 {
568 if ( mReportType != BUG_REPORT )
569 {
570 gViewerWindow->alertXml("HelpReportAbuseSelectCategory");
571 }
572 else
573 {
574 gViewerWindow->alertXml("HelpReportBugSelectCategory");
575 }
576 return;
577 }
578
579 if ( mReportType != BUG_REPORT )
580 {
581 if ( childGetText("abuser_name_edit").empty() )
582 {
583 gViewerWindow->alertXml("HelpReportAbuseAbuserNameEmpty");
584 return;
585 };
586
587 if ( childGetText("abuse_location_edit").empty() )
588 {
589 gViewerWindow->alertXml("HelpReportAbuseAbuserLocationEmpty");
590 return;
591 };
592 };
593
594 if ( childGetText("summary_edit").empty() )
595 {
596 if ( mReportType != BUG_REPORT )
597 {
598 gViewerWindow->alertXml("HelpReportAbuseSummaryEmpty");
599 }
600 else
601 {
602 gViewerWindow->alertXml("HelpReportBugSummaryEmpty");
603 }
604 return;
605 };
606
607 if ( childGetText("details_edit") == mDefaultSummary )
608 {
609 if ( mReportType != BUG_REPORT )
610 {
611 gViewerWindow->alertXml("HelpReportAbuseDetailsEmpty");
612 }
613 else
614 {
615 gViewerWindow->alertXml("HelpReportBugDetailsEmpty");
616 }
617 return;
618 };
619
620 // reset flag in case the next report also contains this text
621 mCopyrightWarningSeen = FALSE;
622
623 U32 check_flags = 0;
624 if (childGetValue("screen_check"))
625 {
626 check_flags |= INCLUDE_SCREENSHOT;
627 }
628
629 LLMessageSystem *msg = gMessageSystem;
630 msg->newMessageFast(_PREHASH_UserReport);
631 msg->nextBlockFast(_PREHASH_AgentData);
632 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
633 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
634 msg->nextBlockFast(_PREHASH_ReportData);
635 msg->addU8Fast(_PREHASH_ReportType, (U8) mReportType);
636 msg->addU8(_PREHASH_Category, category);
637 msg->addVector3Fast(_PREHASH_Position, mPosition);
638 msg->addU8Fast(_PREHASH_CheckFlags, (U8) check_flags);
639
640 // only send a screenshot ID if we're asked too and the email is
641 // going to LL - Estate Owners cannot see the screenshot asset
642 LLSD screenshot_id = LLUUID::null;
643 if (childGetValue("screen_check"))
644 {
645 if ( mReportType != BUG_REPORT )
646 {
647 if ( gEmailToEstateOwner == FALSE )
648 {
649 screenshot_id = childGetValue("screenshot");
650 }
651 }
652 else
653 {
654 screenshot_id = childGetValue("screenshot");
655 };
656 };
657 msg->addUUIDFast(_PREHASH_ScreenshotID, screenshot_id);
658 msg->addUUIDFast(_PREHASH_ObjectID, mObjectID);
659
660 msg->addUUID("AbuserID", mAbuserID );
661 msg->addString("AbuseRegionName", "");
662 msg->addUUID("AbuseRegionID", LLUUID::null);
663
664 std::ostringstream summary;
665 if (!gInProductionGrid)
666 {
667 summary << "Preview ";
668 }
669
670 LLString category_name;
671 LLComboBox* combo = LLUICtrlFactory::getComboBoxByName(this, "category_combo");
672 if (combo)
673 {
674 category_name = combo->getSimpleSelectedItem(); // want label, not value
675 }
676
677#if LL_WINDOWS
678 const char* platform = "Win";
679 const char* short_platform = "O:W";
680#elif LL_DARWIN
681 const char* platform = "Mac";
682 const char* short_platform = "O:M";
683#elif LL_LINUX
684 const char* platform = "Lnx";
685 const char* short_platform = "O:L";
686#else
687 const char* platform = "???";
688 const char* short_platform = "O:?";
689#endif
690
691
692 if ( mReportType == BUG_REPORT)
693 {
694 summary << short_platform << " V" << LL_VERSION_MAJOR << "."
695 << LL_VERSION_MINOR << "."
696 << LL_VERSION_PATCH << "."
697 << LL_VIEWER_BUILD
698 << " (" << regionp->getName() << ")"
699 << "[" << category_name << "] "
700 << "\"" << childGetValue("summary_edit").asString() << "\"";
701 }
702 else
703 {
704 summary << ""
705 << " |" << regionp->getName() << "|" // region reporter is currently in.
706 << " (" << childGetText("abuse_location_edit") << ")" // region abuse occured in (freeform text - no LLRegionPicker tool)
707 << " [" << category_name << "] " // updated category
708 << " {" << childGetText("abuser_name_edit") << "} " // name of abuse entered in report (chosen using LLAvatarPicker)
709 << " \"" << childGetValue("summary_edit").asString() << "\""; // summary as entered
710 };
711 msg->addStringFast(_PREHASH_Summary, summary.str().c_str());
712
713 std::ostringstream details;
714 if (mReportType != BUG_REPORT)
715 {
716 details << "V" << LL_VERSION_MAJOR << "." // client version moved to body of email for abuse reports
717 << LL_VERSION_MINOR << "."
718 << LL_VERSION_PATCH << "."
719 << LL_VIEWER_BUILD << std::endl << std::endl;
720 }
721 LLString object_name = childGetText("object_name");
722 LLString owner_name = childGetText("owner_name");
723 if (!object_name.empty() && !owner_name.empty())
724 {
725 details << "Object: " << object_name << "\n";
726 details << "Owner: " << owner_name << "\n";
727 }
728
729 if ( mReportType != BUG_REPORT )
730 {
731 details << "Abuser name: " << childGetText("abuser_name_edit") << " \n";
732 details << "Abuser location: " << childGetText("abuse_location_edit") << " \n";
733 };
734
735 details << childGetValue("details_edit").asString();
736 msg->addStringFast(_PREHASH_Details, details.str() );
737
738 char version_string[MAX_STRING];
739 sprintf(version_string,
740 "%d.%d.%d %s %s %s %s",
741 LL_VERSION_MAJOR,
742 LL_VERSION_MINOR,
743 LL_VERSION_PATCH,
744 platform,
745 gSysCPU.getFamily().c_str(),
746 gGLManager.mGLRenderer.c_str(),
747 gGLManager.mDriverVersionVendorString.c_str());
748 msg->addString("VersionString", version_string);
749
750 msg->sendReliable(regionp->getHost());
751
752 close();
753}
754
755
756void LLFloaterReporter::uploadScreenshot()
757{
758 const S32 IMAGE_WIDTH = 1024;
759 const S32 IMAGE_HEIGHT = 768;
760 LLString filename("report_screenshot.bmp");
761
762 if( !gViewerWindow->saveSnapshot( filename, IMAGE_WIDTH, IMAGE_HEIGHT, TRUE, FALSE ) )
763 {
764 return;
765 }
766
767 // Generate the temporary filename
768 std::string temp_filename = gDirUtilp->getTempFilename();
769
770 // try to create the upload file
771 if (!LLViewerImageList::createUploadFile(filename,
772 temp_filename,
773 IMG_CODEC_BMP ))
774 {
775 llwarns << "Unable to upload report screenshot " << filename << ":\n\n" << LLImageBase::getLastError() << "\n" << llendl;
776 if(LLFile::remove(temp_filename.c_str()) == -1)
777 {
778 lldebugs << "unable to remove temp file" << llendl;
779 }
780 LLFilePicker::instance().reset();
781 }
782 else
783 {
784 // create a resource data
785 LLResourceData* data = NULL;
786 data = new LLResourceData;
787 data->mInventoryType = LLInventoryType::IT_NONE;
788 data->mAssetInfo.mTransactionID.generate();
789 data->mAssetInfo.mUuid = data->mAssetInfo.mTransactionID.makeAssetID(gAgent.getSecureSessionID());
790 if (BUG_REPORT == mReportType)
791 {
792 //data->mAssetInfo.mType = LLAssetType::AT_BUG_REPORT_SCREENSHOT;
793 data->mAssetInfo.mType = LLAssetType::AT_TEXTURE;
794 data->mPreferredLocation = LLAssetType::EType(-1);
795 }
796 else if (COMPLAINT_REPORT == mReportType)
797 {
798 //data->mAssetInfo.mType = LLAssetType::AT_COMPLAINT_REPORT_SCREENSHOT;
799 data->mAssetInfo.mType = LLAssetType::AT_TEXTURE;
800 data->mPreferredLocation = LLAssetType::EType(-2);
801 }
802 else
803 {
804 llwarns << "Unknown LLFloaterReporter type" << llendl;
805 }
806 data->mAssetInfo.mCreatorID = gAgentID;
807 data->mAssetInfo.setName("screenshot_name");
808 data->mAssetInfo.setDescription("screenshot_descr");
809
810 llinfos << "*** Uploading: " << llendl;
811 llinfos << "Type: " << LLAssetType::lookup(data->mAssetInfo.mType) << llendl;
812 llinfos << "File: " << filename << llendl;
813 llinfos << "Dest: " << temp_filename << llendl;
814 llinfos << "Name: " << data->mAssetInfo.getName() << llendl;
815 llinfos << "Desc: " << data->mAssetInfo.getDescription() << llendl;
816
817 gAssetStorage->storeAssetData(temp_filename.c_str(),
818 data->mAssetInfo.mTransactionID,
819 data->mAssetInfo.mType,
820 LLFloaterReporter::uploadDoneCallback,
821 (void*)data, TRUE);
822 }
823}
824
825
826// static
827void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data, S32 result) // StoreAssetData callback (fixed)
828{
829 LLResourceData* data = (LLResourceData*)user_data;
830
831 if(result >= 0)
832 {
833 EReportType report_type = UNKNOWN_REPORT;
834 if (data->mPreferredLocation == -1)
835 {
836 report_type = BUG_REPORT;
837 }
838 else if (data->mPreferredLocation == -2)
839 {
840 report_type = COMPLAINT_REPORT;
841 }
842 else
843 {
844 llwarns << "Unknown report type : " << data->mPreferredLocation << llendl;
845 }
846
847 LLFloaterReporter *self = getReporter(report_type);
848 if (self)
849 {
850 LLTexturePicker* texture = LLUICtrlFactory::getTexturePickerByName(self, "screenshot");
851 if (texture)
852 {
853 texture->setImageAssetID(uuid);
854 texture->setDefaultImageAssetID(uuid);
855 texture->setCaption("Screenshot");
856 }
857 self->mScreenID = uuid;
858 llinfos << "Got screen shot " << uuid << llendl;
859 }
860 }
861 else // if(result >= 0)
862 {
863 LLStringBase<char>::format_map_t args;
864 args["[REASON]"] = std::string(LLAssetStorage::getErrorString(result));
865 gViewerWindow->alertXml("ErrorUploadingReportScreenshot", args);
866
867 std::string err_msg("There was a problem uploading a report screenshot");
868 err_msg += " due to the following reason: " + args["[REASON]"];
869 llwarns << err_msg << llendl;
870 }
871 delete data;
872}
873
874
875void LLFloaterReporter::setPosBox(const LLVector3d &pos)
876{
877 mPosition.setVec(pos);
878 LLString pos_string = llformat("{%.1f, %.1f, %.1f}",
879 mPosition.mV[VX],
880 mPosition.mV[VY],
881 mPosition.mV[VZ]);
882 childSetText("pos_field", pos_string);
883}
884
885void LLFloaterReporter::setDescription(const LLString& description, LLMeanCollisionData *mcd)
886{
887 LLFloaterReporter *self = gReporterInstances[COMPLAINT_REPORT];
888 if (self)
889 {
890 self->childSetText("details_edit", description);
891
892 for_each(self->mMCDList.begin(), self->mMCDList.end(), DeletePointer());
893 self->mMCDList.clear();
894 if (mcd)
895 {
896 self->mMCDList.push_back(new LLMeanCollisionData(mcd));
897 }
898 }
899}
900
901void LLFloaterReporter::addDescription(const LLString& description, LLMeanCollisionData *mcd)
902{
903 LLFloaterReporter *self = gReporterInstances[COMPLAINT_REPORT];
904 if (self)
905 {
906 LLTextEditor* text = LLUICtrlFactory::getTextEditorByName(self, "details_edit");
907 if (text)
908 {
909 text->insertText(description);
910 }
911 if (mcd)
912 {
913 self->mMCDList.push_back(new LLMeanCollisionData(mcd));
914 }
915 }
916}