diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llfloaterreporter.cpp | |
parent | README.txt (diff) | |
download | meta-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.cpp | 916 |
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 | |||
84 | const 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 | ||
92 | LLMap< 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 | ||
96 | namespace { | ||
97 | static BOOL gEmailToEstateOwner = FALSE; | ||
98 | static BOOL gDialogVisible = FALSE; | ||
99 | } | ||
100 | |||
101 | //----------------------------------------------------------------------------- | ||
102 | // Member functions | ||
103 | //----------------------------------------------------------------------------- | ||
104 | LLFloaterReporter::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 | ||
199 | void 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 | ||
217 | LLFloaterReporter::~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 | ||
242 | void 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 | |||
260 | void 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 | |||
277 | void 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 | ||
353 | void 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 | ||
361 | void 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 | ||
379 | void 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 | ||
411 | void 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 | ||
427 | void 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 | ||
441 | void 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 | ||
456 | void 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 | ||
501 | void 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 | ||
523 | LLFloaterReporter* 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 | |||
534 | LLFloaterReporter* LLFloaterReporter::createNewAbuseReporter() | ||
535 | { | ||
536 | return new LLFloaterReporter("complaint_reporter", | ||
537 | LLRect(), | ||
538 | "Report Abuse", | ||
539 | COMPLAINT_REPORT); | ||
540 | } | ||
541 | |||
542 | //static | ||
543 | LLFloaterReporter* LLFloaterReporter::createNewBugReporter() | ||
544 | { | ||
545 | return new LLFloaterReporter("bug_reporter", | ||
546 | LLRect(), | ||
547 | "Report Bug", | ||
548 | BUG_REPORT); | ||
549 | } | ||
550 | |||
551 | |||
552 | |||
553 | void 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 | |||
559 | void 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 | |||
756 | void 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 | ||
827 | void 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 | |||
875 | void 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 | |||
885 | void 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 | |||
901 | void 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 | } | ||