PageRenderTime 36ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 1ms

/indra/newview/llfloaterreporter.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 877 lines | 625 code | 135 blank | 117 comment | 60 complexity | 603759ec8d22072e3c980d088e9e934f MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llfloaterreporter.cpp
  3. * @brief Abuse reports.
  4. *
  5. * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. // self include
  28. #include "llfloaterreporter.h"
  29. #include <sstream>
  30. // linden library includes
  31. #include "llassetstorage.h"
  32. #include "llavatarnamecache.h"
  33. #include "llcachename.h"
  34. #include "llfontgl.h"
  35. #include "llimagej2c.h"
  36. #include "llinventory.h"
  37. #include "llnotificationsutil.h"
  38. #include "llstring.h"
  39. #include "llsys.h"
  40. #include "llvfile.h"
  41. #include "llvfs.h"
  42. #include "mean_collision_data.h"
  43. #include "message.h"
  44. #include "v3math.h"
  45. // viewer project includes
  46. #include "llagent.h"
  47. #include "llbutton.h"
  48. #include "llfloaterreg.h"
  49. #include "lltexturectrl.h"
  50. #include "llscrolllistctrl.h"
  51. #include "lldispatcher.h"
  52. #include "llviewerobject.h"
  53. #include "llviewerregion.h"
  54. #include "llcombobox.h"
  55. #include "lltooldraganddrop.h"
  56. #include "lluiconstants.h"
  57. #include "lluploaddialog.h"
  58. #include "llcallingcard.h"
  59. #include "llviewerobjectlist.h"
  60. #include "lltoolobjpicker.h"
  61. #include "lltoolmgr.h"
  62. #include "llresourcedata.h" // for LLResourceData
  63. #include "llslurl.h"
  64. #include "llviewerwindow.h"
  65. #include "llviewertexturelist.h"
  66. #include "llworldmap.h"
  67. #include "llfilepicker.h"
  68. #include "llfloateravatarpicker.h"
  69. #include "lldir.h"
  70. #include "llselectmgr.h"
  71. #include "llversioninfo.h"
  72. #include "lluictrlfactory.h"
  73. #include "llviewernetwork.h"
  74. #include "llassetuploadresponders.h"
  75. #include "llagentui.h"
  76. #include "lltrans.h"
  77. const U32 INCLUDE_SCREENSHOT = 0x01 << 0;
  78. //-----------------------------------------------------------------------------
  79. // Globals
  80. //-----------------------------------------------------------------------------
  81. //-----------------------------------------------------------------------------
  82. // Member functions
  83. //-----------------------------------------------------------------------------
  84. LLFloaterReporter::LLFloaterReporter(const LLSD& key)
  85. : LLFloater(key),
  86. mReportType(COMPLAINT_REPORT),
  87. mObjectID(),
  88. mScreenID(),
  89. mAbuserID(),
  90. mOwnerName(),
  91. mDeselectOnClose( FALSE ),
  92. mPicking( FALSE),
  93. mPosition(),
  94. mCopyrightWarningSeen( FALSE ),
  95. mResourceDatap(new LLResourceData())
  96. {
  97. }
  98. // static
  99. void LLFloaterReporter::processRegionInfo(LLMessageSystem* msg)
  100. {
  101. U32 region_flags;
  102. msg->getU32("RegionInfo", "RegionFlags", region_flags);
  103. if ( LLFloaterReg::instanceVisible("reporter") )
  104. {
  105. LLNotificationsUtil::add("HelpReportAbuseEmailLL");
  106. };
  107. }
  108. // virtual
  109. BOOL LLFloaterReporter::postBuild()
  110. {
  111. LLSLURL slurl;
  112. LLAgentUI::buildSLURL(slurl);
  113. getChild<LLUICtrl>("abuse_location_edit")->setValue(slurl.getSLURLString());
  114. enableControls(TRUE);
  115. // convert the position to a string
  116. LLVector3d pos = gAgent.getPositionGlobal();
  117. LLViewerRegion *regionp = gAgent.getRegion();
  118. if (regionp)
  119. {
  120. getChild<LLUICtrl>("sim_field")->setValue(regionp->getName());
  121. pos -= regionp->getOriginGlobal();
  122. }
  123. setPosBox(pos);
  124. // Take a screenshot, but don't draw this floater.
  125. setVisible(FALSE);
  126. takeScreenshot();
  127. setVisible(TRUE);
  128. // Default text to be blank
  129. getChild<LLUICtrl>("object_name")->setValue(LLStringUtil::null);
  130. getChild<LLUICtrl>("owner_name")->setValue(LLStringUtil::null);
  131. mOwnerName = LLStringUtil::null;
  132. getChild<LLUICtrl>("summary_edit")->setFocus(TRUE);
  133. mDefaultSummary = getChild<LLUICtrl>("details_edit")->getValue().asString();
  134. // send a message and ask for information about this region -
  135. // result comes back in processRegionInfo(..)
  136. LLMessageSystem* msg = gMessageSystem;
  137. msg->newMessage("RequestRegionInfo");
  138. msg->nextBlock("AgentData");
  139. msg->addUUID("AgentID", gAgent.getID());
  140. msg->addUUID("SessionID", gAgent.getSessionID());
  141. gAgent.sendReliableMessage();
  142. // abuser name is selected from a list
  143. LLUICtrl* le = getChild<LLUICtrl>("abuser_name_edit");
  144. le->setEnabled( false );
  145. setPosBox((LLVector3d)mPosition.getValue());
  146. LLButton* pick_btn = getChild<LLButton>("pick_btn");
  147. pick_btn->setImages(std::string("tool_face.tga"),
  148. std::string("tool_face_active.tga") );
  149. childSetAction("pick_btn", onClickObjPicker, this);
  150. childSetAction("select_abuser", boost::bind(&LLFloaterReporter::onClickSelectAbuser, this));
  151. childSetAction("send_btn", onClickSend, this);
  152. childSetAction("cancel_btn", onClickCancel, this);
  153. // grab the user's name
  154. std::string reporter = LLSLURL("agent", gAgent.getID(), "inspect").getSLURLString();
  155. getChild<LLUICtrl>("reporter_field")->setValue(reporter);
  156. center();
  157. return TRUE;
  158. }
  159. // virtual
  160. LLFloaterReporter::~LLFloaterReporter()
  161. {
  162. // child views automatically deleted
  163. mObjectID = LLUUID::null;
  164. if (mPicking)
  165. {
  166. closePickTool(this);
  167. }
  168. mPosition.setVec(0.0f, 0.0f, 0.0f);
  169. std::for_each(mMCDList.begin(), mMCDList.end(), DeletePointer() );
  170. mMCDList.clear();
  171. delete mResourceDatap;
  172. }
  173. // virtual
  174. void LLFloaterReporter::draw()
  175. {
  176. getChildView("screen_check")->setEnabled(TRUE );
  177. LLFloater::draw();
  178. }
  179. void LLFloaterReporter::enableControls(BOOL enable)
  180. {
  181. getChildView("category_combo")->setEnabled(enable);
  182. getChildView("chat_check")->setEnabled(enable);
  183. getChildView("screen_check")->setEnabled(enable);
  184. getChildView("screenshot")->setEnabled(FALSE);
  185. getChildView("pick_btn")->setEnabled(enable);
  186. getChildView("summary_edit")->setEnabled(enable);
  187. getChildView("details_edit")->setEnabled(enable);
  188. getChildView("send_btn")->setEnabled(enable);
  189. getChildView("cancel_btn")->setEnabled(enable);
  190. }
  191. void LLFloaterReporter::getObjectInfo(const LLUUID& object_id)
  192. {
  193. // TODO --
  194. // 1 need to send to correct simulator if object is not
  195. // in same simulator as agent
  196. // 2 display info in widget window that gives feedback that
  197. // we have recorded the object info
  198. // 3 can pick avatar ==> might want to indicate when a picked
  199. // object is an avatar, attachment, or other category
  200. mObjectID = object_id;
  201. if (LLUUID::null != mObjectID)
  202. {
  203. // get object info for the user's benefit
  204. LLViewerObject* objectp = NULL;
  205. objectp = gObjectList.findObject( mObjectID );
  206. if (objectp)
  207. {
  208. if ( objectp->isAttachment() )
  209. {
  210. objectp = (LLViewerObject*)objectp->getRoot();
  211. mObjectID = objectp->getID();
  212. }
  213. // correct the region and position information
  214. LLViewerRegion *regionp = objectp->getRegion();
  215. if (regionp)
  216. {
  217. getChild<LLUICtrl>("sim_field")->setValue(regionp->getName());
  218. LLVector3d global_pos;
  219. global_pos.setVec(objectp->getPositionRegion());
  220. setPosBox(global_pos);
  221. }
  222. if (objectp->isAvatar())
  223. {
  224. setFromAvatarID(mObjectID);
  225. }
  226. else
  227. {
  228. // we have to query the simulator for information
  229. // about this object
  230. LLMessageSystem* msg = gMessageSystem;
  231. U32 request_flags = COMPLAINT_REPORT_REQUEST;
  232. msg->newMessageFast(_PREHASH_RequestObjectPropertiesFamily);
  233. msg->nextBlockFast(_PREHASH_AgentData);
  234. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  235. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  236. msg->nextBlockFast(_PREHASH_ObjectData);
  237. msg->addU32Fast(_PREHASH_RequestFlags, request_flags );
  238. msg->addUUIDFast(_PREHASH_ObjectID, mObjectID);
  239. LLViewerRegion* regionp = objectp->getRegion();
  240. msg->sendReliable( regionp->getHost() );
  241. }
  242. }
  243. }
  244. }
  245. void LLFloaterReporter::onClickSelectAbuser()
  246. {
  247. gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLFloaterReporter::callbackAvatarID, this, _1, _2), FALSE, TRUE ));
  248. }
  249. void LLFloaterReporter::callbackAvatarID(const uuid_vec_t& ids, const std::vector<LLAvatarName> names)
  250. {
  251. if (ids.empty() || names.empty()) return;
  252. getChild<LLUICtrl>("abuser_name_edit")->setValue(names[0].getCompleteName());
  253. mAbuserID = ids[0];
  254. refresh();
  255. }
  256. void LLFloaterReporter::setFromAvatarID(const LLUUID& avatar_id)
  257. {
  258. mAbuserID = mObjectID = avatar_id;
  259. std::string avatar_link = LLSLURL("agent", mObjectID, "inspect").getSLURLString();
  260. getChild<LLUICtrl>("owner_name")->setValue(avatar_link);
  261. LLAvatarNameCache::get(avatar_id, boost::bind(&LLFloaterReporter::onAvatarNameCache, this, _1, _2));
  262. }
  263. void LLFloaterReporter::onAvatarNameCache(const LLUUID& avatar_id, const LLAvatarName& av_name)
  264. {
  265. if (mObjectID == avatar_id)
  266. {
  267. mOwnerName = av_name.getCompleteName();
  268. getChild<LLUICtrl>("object_name")->setValue(av_name.getCompleteName());
  269. getChild<LLUICtrl>("object_name")->setToolTip(av_name.getCompleteName());
  270. getChild<LLUICtrl>("abuser_name_edit")->setValue(av_name.getCompleteName());
  271. }
  272. }
  273. // static
  274. void LLFloaterReporter::onClickSend(void *userdata)
  275. {
  276. LLFloaterReporter *self = (LLFloaterReporter *)userdata;
  277. if (self->mPicking)
  278. {
  279. closePickTool(self);
  280. }
  281. if(self->validateReport())
  282. {
  283. const int IP_CONTENT_REMOVAL = 66;
  284. const int IP_PERMISSONS_EXPLOIT = 37;
  285. LLComboBox* combo = self->getChild<LLComboBox>( "category_combo");
  286. int category_value = combo->getSelectedValue().asInteger();
  287. if ( ! self->mCopyrightWarningSeen )
  288. {
  289. std::string details_lc = self->getChild<LLUICtrl>("details_edit")->getValue().asString();
  290. LLStringUtil::toLower( details_lc );
  291. std::string summary_lc = self->getChild<LLUICtrl>("summary_edit")->getValue().asString();
  292. LLStringUtil::toLower( summary_lc );
  293. if ( details_lc.find( "copyright" ) != std::string::npos ||
  294. summary_lc.find( "copyright" ) != std::string::npos ||
  295. category_value == IP_CONTENT_REMOVAL ||
  296. category_value == IP_PERMISSONS_EXPLOIT)
  297. {
  298. LLNotificationsUtil::add("HelpReportAbuseContainsCopyright");
  299. self->mCopyrightWarningSeen = TRUE;
  300. return;
  301. }
  302. }
  303. else if (category_value == IP_CONTENT_REMOVAL)
  304. {
  305. // IP_CONTENT_REMOVAL *always* shows the dialog -
  306. // ergo you can never send that abuse report type.
  307. LLNotificationsUtil::add("HelpReportAbuseContainsCopyright");
  308. return;
  309. }
  310. LLUploadDialog::modalUploadDialog(LLTrans::getString("uploading_abuse_report"));
  311. // *TODO don't upload image if checkbox isn't checked
  312. std::string url = gAgent.getRegion()->getCapability("SendUserReport");
  313. std::string sshot_url = gAgent.getRegion()->getCapability("SendUserReportWithScreenshot");
  314. if(!url.empty() || !sshot_url.empty())
  315. {
  316. self->sendReportViaCaps(url, sshot_url, self->gatherReport());
  317. self->closeFloater();
  318. }
  319. else
  320. {
  321. if(self->getChild<LLUICtrl>("screen_check")->getValue())
  322. {
  323. self->getChildView("send_btn")->setEnabled(FALSE);
  324. self->getChildView("cancel_btn")->setEnabled(FALSE);
  325. // the callback from uploading the image calls sendReportViaLegacy()
  326. self->uploadImage();
  327. }
  328. else
  329. {
  330. self->sendReportViaLegacy(self->gatherReport());
  331. LLUploadDialog::modalUploadFinished();
  332. self->closeFloater();
  333. }
  334. }
  335. }
  336. }
  337. // static
  338. void LLFloaterReporter::onClickCancel(void *userdata)
  339. {
  340. LLFloaterReporter *self = (LLFloaterReporter *)userdata;
  341. // reset flag in case the next report also contains this text
  342. self->mCopyrightWarningSeen = FALSE;
  343. if (self->mPicking)
  344. {
  345. closePickTool(self);
  346. }
  347. self->closeFloater();
  348. }
  349. // static
  350. void LLFloaterReporter::onClickObjPicker(void *userdata)
  351. {
  352. LLFloaterReporter *self = (LLFloaterReporter *)userdata;
  353. LLToolObjPicker::getInstance()->setExitCallback(LLFloaterReporter::closePickTool, self);
  354. LLToolMgr::getInstance()->setTransientTool(LLToolObjPicker::getInstance());
  355. self->mPicking = TRUE;
  356. self->getChild<LLUICtrl>("object_name")->setValue(LLStringUtil::null);
  357. self->getChild<LLUICtrl>("owner_name")->setValue(LLStringUtil::null);
  358. self->mOwnerName = LLStringUtil::null;
  359. LLButton* pick_btn = self->getChild<LLButton>("pick_btn");
  360. if (pick_btn) pick_btn->setToggleState(TRUE);
  361. }
  362. // static
  363. void LLFloaterReporter::closePickTool(void *userdata)
  364. {
  365. LLFloaterReporter *self = (LLFloaterReporter *)userdata;
  366. LLUUID object_id = LLToolObjPicker::getInstance()->getObjectID();
  367. self->getObjectInfo(object_id);
  368. LLToolMgr::getInstance()->clearTransientTool();
  369. self->mPicking = FALSE;
  370. LLButton* pick_btn = self->getChild<LLButton>("pick_btn");
  371. if (pick_btn) pick_btn->setToggleState(FALSE);
  372. }
  373. // static
  374. void LLFloaterReporter::showFromMenu(EReportType report_type)
  375. {
  376. if (COMPLAINT_REPORT != report_type)
  377. {
  378. llwarns << "Unknown LLViewerReporter type : " << report_type << llendl;
  379. return;
  380. }
  381. LLFloaterReporter* f = LLFloaterReg::showTypedInstance<LLFloaterReporter>("reporter", LLSD());
  382. if (f)
  383. {
  384. f->setReportType(report_type);
  385. }
  386. }
  387. // static
  388. void LLFloaterReporter::show(const LLUUID& object_id, const std::string& avatar_name)
  389. {
  390. LLFloaterReporter* f = LLFloaterReg::showTypedInstance<LLFloaterReporter>("reporter");
  391. if (avatar_name.empty())
  392. {
  393. // Request info for this object
  394. f->getObjectInfo(object_id);
  395. }
  396. else
  397. {
  398. f->setFromAvatarID(object_id);
  399. }
  400. // Need to deselect on close
  401. f->mDeselectOnClose = TRUE;
  402. f->openFloater();
  403. }
  404. // static
  405. void LLFloaterReporter::showFromObject(const LLUUID& object_id)
  406. {
  407. show(object_id);
  408. }
  409. // static
  410. void LLFloaterReporter::showFromAvatar(const LLUUID& avatar_id, const std::string avatar_name)
  411. {
  412. show(avatar_id, avatar_name);
  413. }
  414. void LLFloaterReporter::setPickedObjectProperties(const std::string& object_name, const std::string& owner_name, const LLUUID owner_id)
  415. {
  416. getChild<LLUICtrl>("object_name")->setValue(object_name);
  417. std::string owner_link =
  418. LLSLURL("agent", owner_id, "inspect").getSLURLString();
  419. getChild<LLUICtrl>("owner_name")->setValue(owner_link);
  420. getChild<LLUICtrl>("abuser_name_edit")->setValue(owner_name);
  421. mAbuserID = owner_id;
  422. mOwnerName = owner_name;
  423. }
  424. bool LLFloaterReporter::validateReport()
  425. {
  426. // Ensure user selected a category from the list
  427. LLSD category_sd = getChild<LLUICtrl>("category_combo")->getValue();
  428. U8 category = (U8)category_sd.asInteger();
  429. if (category == 0)
  430. {
  431. LLNotificationsUtil::add("HelpReportAbuseSelectCategory");
  432. return false;
  433. }
  434. if ( getChild<LLUICtrl>("abuser_name_edit")->getValue().asString().empty() )
  435. {
  436. LLNotificationsUtil::add("HelpReportAbuseAbuserNameEmpty");
  437. return false;
  438. };
  439. if ( getChild<LLUICtrl>("abuse_location_edit")->getValue().asString().empty() )
  440. {
  441. LLNotificationsUtil::add("HelpReportAbuseAbuserLocationEmpty");
  442. return false;
  443. };
  444. if ( getChild<LLUICtrl>("abuse_location_edit")->getValue().asString().empty() )
  445. {
  446. LLNotificationsUtil::add("HelpReportAbuseAbuserLocationEmpty");
  447. return false;
  448. };
  449. if ( getChild<LLUICtrl>("summary_edit")->getValue().asString().empty() )
  450. {
  451. LLNotificationsUtil::add("HelpReportAbuseSummaryEmpty");
  452. return false;
  453. };
  454. if ( getChild<LLUICtrl>("details_edit")->getValue().asString() == mDefaultSummary )
  455. {
  456. LLNotificationsUtil::add("HelpReportAbuseDetailsEmpty");
  457. return false;
  458. };
  459. return true;
  460. }
  461. LLSD LLFloaterReporter::gatherReport()
  462. {
  463. LLViewerRegion *regionp = gAgent.getRegion();
  464. if (!regionp) return LLSD(); // *TODO handle this failure case more gracefully
  465. // reset flag in case the next report also contains this text
  466. mCopyrightWarningSeen = FALSE;
  467. std::ostringstream summary;
  468. if (!LLGridManager::getInstance()->isInProductionGrid())
  469. {
  470. summary << "Preview ";
  471. }
  472. std::string category_name;
  473. LLComboBox* combo = getChild<LLComboBox>( "category_combo");
  474. if (combo)
  475. {
  476. category_name = combo->getSelectedItemLabel(); // want label, not value
  477. }
  478. #if LL_WINDOWS
  479. const char* platform = "Win";
  480. #elif LL_DARWIN
  481. const char* platform = "Mac";
  482. #elif LL_LINUX
  483. const char* platform = "Lnx";
  484. #elif LL_SOLARIS
  485. const char* platform = "Sol";
  486. const char* short_platform = "O:S";
  487. #else
  488. const char* platform = "???";
  489. #endif
  490. summary << ""
  491. << " |" << regionp->getName() << "|" // region reporter is currently in.
  492. << " (" << getChild<LLUICtrl>("abuse_location_edit")->getValue().asString() << ")" // region abuse occured in (freeform text - no LLRegionPicker tool)
  493. << " [" << category_name << "] " // updated category
  494. << " {" << getChild<LLUICtrl>("abuser_name_edit")->getValue().asString() << "} " // name of abuse entered in report (chosen using LLAvatarPicker)
  495. << " \"" << getChild<LLUICtrl>("summary_edit")->getValue().asString() << "\""; // summary as entered
  496. std::ostringstream details;
  497. details << "V" << LLVersionInfo::getVersion() << std::endl << std::endl; // client version moved to body of email for abuse reports
  498. std::string object_name = getChild<LLUICtrl>("object_name")->getValue().asString();
  499. if (!object_name.empty() && !mOwnerName.empty())
  500. {
  501. details << "Object: " << object_name << "\n";
  502. details << "Owner: " << mOwnerName << "\n";
  503. }
  504. details << "Abuser name: " << getChild<LLUICtrl>("abuser_name_edit")->getValue().asString() << " \n";
  505. details << "Abuser location: " << getChild<LLUICtrl>("abuse_location_edit")->getValue().asString() << " \n";
  506. details << getChild<LLUICtrl>("details_edit")->getValue().asString();
  507. std::string version_string;
  508. version_string = llformat(
  509. "%s %s %s %s %s",
  510. LLVersionInfo::getShortVersion().c_str(),
  511. platform,
  512. gSysCPU.getFamily().c_str(),
  513. gGLManager.mGLRenderer.c_str(),
  514. gGLManager.mDriverVersionVendorString.c_str());
  515. // only send a screenshot ID if we're asked to and the email is
  516. // going to LL - Estate Owners cannot see the screenshot asset
  517. LLUUID screenshot_id = LLUUID::null;
  518. if (getChild<LLUICtrl>("screen_check")->getValue())
  519. {
  520. screenshot_id = getChild<LLUICtrl>("screenshot")->getValue();
  521. };
  522. LLSD report = LLSD::emptyMap();
  523. report["report-type"] = (U8) mReportType;
  524. report["category"] = getChild<LLUICtrl>("category_combo")->getValue();
  525. report["position"] = mPosition.getValue();
  526. report["check-flags"] = (U8)0; // this is not used
  527. report["screenshot-id"] = screenshot_id;
  528. report["object-id"] = mObjectID;
  529. report["abuser-id"] = mAbuserID;
  530. report["abuse-region-name"] = "";
  531. report["abuse-region-id"] = LLUUID::null;
  532. report["summary"] = summary.str();
  533. report["version-string"] = version_string;
  534. report["details"] = details.str();
  535. return report;
  536. }
  537. void LLFloaterReporter::sendReportViaLegacy(const LLSD & report)
  538. {
  539. LLViewerRegion *regionp = gAgent.getRegion();
  540. if (!regionp) return;
  541. LLMessageSystem *msg = gMessageSystem;
  542. msg->newMessageFast(_PREHASH_UserReport);
  543. msg->nextBlockFast(_PREHASH_AgentData);
  544. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  545. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  546. msg->nextBlockFast(_PREHASH_ReportData);
  547. msg->addU8Fast(_PREHASH_ReportType, report["report-type"].asInteger());
  548. msg->addU8(_PREHASH_Category, report["category"].asInteger());
  549. msg->addVector3Fast(_PREHASH_Position, LLVector3(report["position"]));
  550. msg->addU8Fast(_PREHASH_CheckFlags, report["check-flags"].asInteger());
  551. msg->addUUIDFast(_PREHASH_ScreenshotID, report["screenshot-id"].asUUID());
  552. msg->addUUIDFast(_PREHASH_ObjectID, report["object-id"].asUUID());
  553. msg->addUUID("AbuserID", report["abuser-id"].asUUID());
  554. msg->addString("AbuseRegionName", report["abuse-region-name"].asString());
  555. msg->addUUID("AbuseRegionID", report["abuse-region-id"].asUUID());
  556. msg->addStringFast(_PREHASH_Summary, report["summary"].asString());
  557. msg->addString("VersionString", report["version-string"]);
  558. msg->addStringFast(_PREHASH_Details, report["details"] );
  559. msg->sendReliable(regionp->getHost());
  560. }
  561. class LLUserReportScreenshotResponder : public LLAssetUploadResponder
  562. {
  563. public:
  564. LLUserReportScreenshotResponder(const LLSD & post_data,
  565. const LLUUID & vfile_id,
  566. LLAssetType::EType asset_type):
  567. LLAssetUploadResponder(post_data, vfile_id, asset_type)
  568. {
  569. }
  570. void uploadFailed(const LLSD& content)
  571. {
  572. // *TODO pop up a dialog so the user knows their report screenshot didn't make it
  573. LLUploadDialog::modalUploadFinished();
  574. }
  575. void uploadComplete(const LLSD& content)
  576. {
  577. // we don't care about what the server returns from this post, just clean up the UI
  578. LLUploadDialog::modalUploadFinished();
  579. }
  580. };
  581. class LLUserReportResponder : public LLHTTPClient::Responder
  582. {
  583. public:
  584. LLUserReportResponder(): LLHTTPClient::Responder() {}
  585. void error(U32 status, const std::string& reason)
  586. {
  587. // *TODO do some user messaging here
  588. LLUploadDialog::modalUploadFinished();
  589. }
  590. void result(const LLSD& content)
  591. {
  592. // we don't care about what the server returns
  593. LLUploadDialog::modalUploadFinished();
  594. }
  595. };
  596. void LLFloaterReporter::sendReportViaCaps(std::string url, std::string sshot_url, const LLSD& report)
  597. {
  598. if(getChild<LLUICtrl>("screen_check")->getValue().asBoolean() && !sshot_url.empty())
  599. {
  600. // try to upload screenshot
  601. LLHTTPClient::post(sshot_url, report, new LLUserReportScreenshotResponder(report,
  602. mResourceDatap->mAssetInfo.mUuid,
  603. mResourceDatap->mAssetInfo.mType));
  604. }
  605. else
  606. {
  607. // screenshot not wanted or we don't have screenshot cap
  608. LLHTTPClient::post(url, report, new LLUserReportResponder());
  609. }
  610. }
  611. void LLFloaterReporter::takeScreenshot()
  612. {
  613. const S32 IMAGE_WIDTH = 1024;
  614. const S32 IMAGE_HEIGHT = 768;
  615. LLPointer<LLImageRaw> raw = new LLImageRaw;
  616. if( !gViewerWindow->rawSnapshot(raw, IMAGE_WIDTH, IMAGE_HEIGHT, TRUE, FALSE, TRUE, FALSE))
  617. {
  618. llwarns << "Unable to take screenshot" << llendl;
  619. return;
  620. }
  621. LLPointer<LLImageJ2C> upload_data = LLViewerTextureList::convertToUploadFile(raw);
  622. // create a resource data
  623. mResourceDatap->mInventoryType = LLInventoryType::IT_NONE;
  624. mResourceDatap->mNextOwnerPerm = 0; // not used
  625. mResourceDatap->mExpectedUploadCost = 0; // we expect that abuse screenshots are free
  626. mResourceDatap->mAssetInfo.mTransactionID.generate();
  627. mResourceDatap->mAssetInfo.mUuid = mResourceDatap->mAssetInfo.mTransactionID.makeAssetID(gAgent.getSecureSessionID());
  628. if (COMPLAINT_REPORT == mReportType)
  629. {
  630. mResourceDatap->mAssetInfo.mType = LLAssetType::AT_TEXTURE;
  631. mResourceDatap->mPreferredLocation = LLFolderType::EType(LLResourceData::INVALID_LOCATION);
  632. }
  633. else
  634. {
  635. llwarns << "Unknown LLFloaterReporter type" << llendl;
  636. }
  637. mResourceDatap->mAssetInfo.mCreatorID = gAgentID;
  638. mResourceDatap->mAssetInfo.setName("screenshot_name");
  639. mResourceDatap->mAssetInfo.setDescription("screenshot_descr");
  640. // store in VFS
  641. LLVFile::writeFile(upload_data->getData(),
  642. upload_data->getDataSize(),
  643. gVFS,
  644. mResourceDatap->mAssetInfo.mUuid,
  645. mResourceDatap->mAssetInfo.mType);
  646. // store in the image list so it doesn't try to fetch from the server
  647. LLPointer<LLViewerFetchedTexture> image_in_list =
  648. LLViewerTextureManager::getFetchedTexture(mResourceDatap->mAssetInfo.mUuid, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::FETCHED_TEXTURE);
  649. image_in_list->createGLTexture(0, raw, 0, TRUE, LLViewerTexture::OTHER);
  650. // the texture picker then uses that texture
  651. LLTexturePicker* texture = getChild<LLTextureCtrl>("screenshot");
  652. if (texture)
  653. {
  654. texture->setImageAssetID(mResourceDatap->mAssetInfo.mUuid);
  655. texture->setDefaultImageAssetID(mResourceDatap->mAssetInfo.mUuid);
  656. texture->setCaption(getString("Screenshot"));
  657. }
  658. }
  659. void LLFloaterReporter::uploadImage()
  660. {
  661. llinfos << "*** Uploading: " << llendl;
  662. llinfos << "Type: " << LLAssetType::lookup(mResourceDatap->mAssetInfo.mType) << llendl;
  663. llinfos << "UUID: " << mResourceDatap->mAssetInfo.mUuid << llendl;
  664. llinfos << "Name: " << mResourceDatap->mAssetInfo.getName() << llendl;
  665. llinfos << "Desc: " << mResourceDatap->mAssetInfo.getDescription() << llendl;
  666. gAssetStorage->storeAssetData(mResourceDatap->mAssetInfo.mTransactionID,
  667. mResourceDatap->mAssetInfo.mType,
  668. LLFloaterReporter::uploadDoneCallback,
  669. (void*)mResourceDatap, TRUE);
  670. }
  671. // static
  672. void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data, S32 result, LLExtStat ext_status) // StoreAssetData callback (fixed)
  673. {
  674. LLUploadDialog::modalUploadFinished();
  675. LLResourceData* data = (LLResourceData*)user_data;
  676. if(result < 0)
  677. {
  678. LLSD args;
  679. args["REASON"] = std::string(LLAssetStorage::getErrorString(result));
  680. LLNotificationsUtil::add("ErrorUploadingReportScreenshot", args);
  681. std::string err_msg("There was a problem uploading a report screenshot");
  682. err_msg += " due to the following reason: " + args["REASON"].asString();
  683. llwarns << err_msg << llendl;
  684. return;
  685. }
  686. EReportType report_type = UNKNOWN_REPORT;
  687. if (data->mPreferredLocation == LLResourceData::INVALID_LOCATION)
  688. {
  689. report_type = COMPLAINT_REPORT;
  690. }
  691. else
  692. {
  693. llwarns << "Unknown report type : " << data->mPreferredLocation << llendl;
  694. }
  695. LLFloaterReporter *self = LLFloaterReg::findTypedInstance<LLFloaterReporter>("reporter");
  696. if (self)
  697. {
  698. self->mScreenID = uuid;
  699. llinfos << "Got screen shot " << uuid << llendl;
  700. self->sendReportViaLegacy(self->gatherReport());
  701. self->closeFloater();
  702. }
  703. }
  704. void LLFloaterReporter::setPosBox(const LLVector3d &pos)
  705. {
  706. mPosition.setVec(pos);
  707. std::string pos_string = llformat("{%.1f, %.1f, %.1f}",
  708. mPosition.mV[VX],
  709. mPosition.mV[VY],
  710. mPosition.mV[VZ]);
  711. getChild<LLUICtrl>("pos_field")->setValue(pos_string);
  712. }
  713. // void LLFloaterReporter::setDescription(const std::string& description, LLMeanCollisionData *mcd)
  714. // {
  715. // LLFloaterReporter *self = LLFloaterReg::findTypedInstance<LLFloaterReporter>("reporter");
  716. // if (self)
  717. // {
  718. // self->getChild<LLUICtrl>("details_edit")->setValue(description);
  719. // for_each(self->mMCDList.begin(), self->mMCDList.end(), DeletePointer());
  720. // self->mMCDList.clear();
  721. // if (mcd)
  722. // {
  723. // self->mMCDList.push_back(new LLMeanCollisionData(mcd));
  724. // }
  725. // }
  726. // }
  727. // void LLFloaterReporter::addDescription(const std::string& description, LLMeanCollisionData *mcd)
  728. // {
  729. // LLFloaterReporter *self = LLFloaterReg::findTypedInstance<LLFloaterReporter>("reporter");
  730. // if (self)
  731. // {
  732. // LLTextEditor* text = self->getChild<LLTextEditor>("details_edit");
  733. // if (text)
  734. // {
  735. // text->insertText(description);
  736. // }
  737. // if (mcd)
  738. // {
  739. // self->mMCDList.push_back(new LLMeanCollisionData(mcd));
  740. // }
  741. // }
  742. // }