diff options
Diffstat (limited to 'indra/newview/llfloaterreporter.cpp')
-rw-r--r-- | indra/newview/llfloaterreporter.cpp | 2090 |
1 files changed, 1045 insertions, 1045 deletions
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 8e58381751..e2c6305f4f 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -1,1045 +1,1045 @@ -/**
- * @file llfloaterreporter.cpp
- * @brief Abuse reports.
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-// self include
-#include "llfloaterreporter.h"
-
-#include <sstream>
-
-// linden library includes
-#include "llassetstorage.h"
-#include "llavatarnamecache.h"
-#include "llcachename.h"
-#include "llcallbacklist.h"
-#include "llcheckboxctrl.h"
-#include "llfontgl.h"
-#include "llimagepng.h"
-#include "llimagej2c.h"
-#include "llinventory.h"
-#include "llnotificationsutil.h"
-#include "llstring.h"
-#include "llsys.h"
-#include "llfilesystem.h"
-#include "mean_collision_data.h"
-#include "message.h"
-#include "v3math.h"
-
-// viewer project includes
-#include "llagent.h"
-#include "llbutton.h"
-#include "llfloaterreg.h"
-#include "lltexturectrl.h"
-#include "lltexteditor.h"
-#include "llscrolllistctrl.h"
-#include "lldispatcher.h"
-#include "llviewerobject.h"
-#include "llviewerregion.h"
-#include "llcombobox.h"
-#include "lltooldraganddrop.h"
-#include "lluiconstants.h"
-#include "lluploaddialog.h"
-#include "llcallingcard.h"
-#include "llviewerobjectlist.h"
-#include "lltoolobjpicker.h"
-#include "lltoolmgr.h"
-#include "llresourcedata.h" // for LLResourceData
-#include "llslurl.h"
-#include "llviewerwindow.h"
-#include "llviewertexturelist.h"
-#include "llworldmap.h"
-#include "llfilepicker.h"
-#include "llfloateravatarpicker.h"
-#include "lldir.h"
-#include "llselectmgr.h"
-#include "llversioninfo.h"
-#include "lluictrlfactory.h"
-#include "llviewercontrol.h"
-#include "llviewernetwork.h"
-
-#include "llagentui.h"
-
-#include "lltrans.h"
-#include "llexperiencecache.h"
-
-#include "llcorehttputil.h"
-#include "llviewerassetupload.h"
-
-const std::string SCREEN_PREV_FILENAME = "screen_report_last.png";
-
-//=========================================================================
-//-----------------------------------------------------------------------------
-// Support classes
-//-----------------------------------------------------------------------------
-class LLARScreenShotUploader : public LLResourceUploadInfo
-{
-public:
- LLARScreenShotUploader(LLSD report, LLUUID assetId, LLAssetType::EType assetType);
-
- virtual LLSD prepareUpload();
- virtual LLSD generatePostBody();
- virtual LLUUID finishUpload(LLSD &result);
-
- virtual bool showInventoryPanel() const { return false; }
- virtual std::string getDisplayName() const { return "Abuse Report"; }
-
-private:
-
- LLSD mReport;
-};
-
-LLARScreenShotUploader::LLARScreenShotUploader(LLSD report, LLUUID assetId, LLAssetType::EType assetType) :
- LLResourceUploadInfo(assetId, assetType, "Abuse Report"),
- mReport(report)
-{
-}
-
-LLSD LLARScreenShotUploader::prepareUpload()
-{
- return LLSD().with("success", LLSD::Boolean(true));
-}
-
-LLSD LLARScreenShotUploader::generatePostBody()
-{ // The report was pregenerated and passed in the constructor.
- return mReport;
-}
-
-LLUUID LLARScreenShotUploader::finishUpload(LLSD &result)
-{
- /* *TODO$: Report success or failure. Carried over from previous todo on responder*/
- return LLUUID::null;
-}
-
-
-//=========================================================================
-//-----------------------------------------------------------------------------
-// Globals
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// Member functions
-//-----------------------------------------------------------------------------
-
-LLFloaterReporter::LLFloaterReporter(const LLSD& key)
-: LLFloater(key),
- mReportType(COMPLAINT_REPORT),
- mObjectID(),
- mScreenID(),
- mAbuserID(),
- mOwnerName(),
- mDeselectOnClose( false ),
- mPicking( false),
- mPosition(),
- mCopyrightWarningSeen( false ),
- mResourceDatap(new LLResourceData()),
- mAvatarNameCacheConnection()
-{
- gIdleCallbacks.addFunction(onIdle, this);
-}
-
-// virtual
-bool LLFloaterReporter::postBuild()
-{
- LLSLURL slurl;
- LLAgentUI::buildSLURL(slurl);
- getChild<LLUICtrl>("abuse_location_edit")->setValue(slurl.getSLURLString());
-
- enableControls(true);
-
- // convert the position to a string
- LLVector3d pos = gAgent.getPositionGlobal();
- LLViewerRegion *regionp = gAgent.getRegion();
- if (regionp)
- {
- getChild<LLUICtrl>("sim_field")->setValue(regionp->getName());
- pos -= regionp->getOriginGlobal();
- }
- setPosBox(pos);
-
- // Default text to be blank
- getChild<LLUICtrl>("object_name")->setValue(LLStringUtil::null);
- getChild<LLUICtrl>("owner_name")->setValue(LLStringUtil::null);
- mOwnerName = LLStringUtil::null;
-
- getChild<LLUICtrl>("summary_edit")->setFocus(true);
-
- mDefaultSummary = getChild<LLUICtrl>("details_edit")->getValue().asString();
-
- // abuser name is selected from a list
- LLUICtrl* le = getChild<LLUICtrl>("abuser_name_edit");
- le->setEnabled( false );
-
- setPosBox((LLVector3d)mPosition.getValue());
- LLButton* pick_btn = getChild<LLButton>("pick_btn");
- pick_btn->setImages(std::string("tool_face.tga"),
- std::string("tool_face_active.tga") );
- childSetAction("pick_btn", onClickObjPicker, this);
-
- childSetAction("select_abuser", boost::bind(&LLFloaterReporter::onClickSelectAbuser, this));
-
- childSetAction("send_btn", onClickSend, this);
- childSetAction("cancel_btn", onClickCancel, this);
-
- // grab the user's name
- std::string reporter = LLSLURL("agent", gAgent.getID(), "inspect").getSLURLString();
- getChild<LLUICtrl>("reporter_field")->setValue(reporter);
-
- // request categories
- if (gAgent.getRegion()
- && gAgent.getRegion()->capabilitiesReceived())
- {
- std::string cap_url = gAgent.getRegionCapability("AbuseCategories");
-
- if (!cap_url.empty())
- {
- std::string lang = gSavedSettings.getString("Language");
- if (lang != "default" && !lang.empty())
- {
- cap_url += "?lc=";
- cap_url += lang;
- }
- LLCoros::instance().launch("LLFloaterReporter::requestAbuseCategoriesCoro",
- boost::bind(LLFloaterReporter::requestAbuseCategoriesCoro, cap_url, this->getHandle()));
- }
- }
-
- center();
-
- return true;
-}
-
-// virtual
-LLFloaterReporter::~LLFloaterReporter()
-{
- if (mAvatarNameCacheConnection.connected())
- {
- mAvatarNameCacheConnection.disconnect();
- }
- gIdleCallbacks.deleteFunction(onIdle, this);
-
- // child views automatically deleted
- mObjectID = LLUUID::null;
-
- if (mPicking)
- {
- closePickTool(this);
- }
-
- mPosition.setVec(0.0f, 0.0f, 0.0f);
-
- delete mResourceDatap;
-}
-
-void LLFloaterReporter::onIdle(void* user_data)
-{
- LLFloaterReporter* floater_reporter = (LLFloaterReporter*)user_data;
- if (floater_reporter)
- {
- static LLCachedControl<F32> screenshot_delay(gSavedSettings, "AbuseReportScreenshotDelay");
- if (floater_reporter->mSnapshotTimer.getStarted() && floater_reporter->mSnapshotTimer.getElapsedTimeF32() > screenshot_delay)
- {
- floater_reporter->mSnapshotTimer.stop();
- floater_reporter->takeNewSnapshot();
- }
- }
-}
-
-void LLFloaterReporter::enableControls(bool enable)
-{
- getChildView("category_combo")->setEnabled(enable);
- getChildView("chat_check")->setEnabled(enable);
- getChildView("screenshot")->setEnabled(false);
- getChildView("pick_btn")->setEnabled(enable);
- getChildView("summary_edit")->setEnabled(enable);
- getChildView("details_edit")->setEnabled(enable);
- getChildView("send_btn")->setEnabled(enable);
- getChildView("cancel_btn")->setEnabled(enable);
-}
-
-void LLFloaterReporter::getExperienceInfo(const LLUUID& experience_id)
-{
- mExperienceID = experience_id;
-
- if (LLUUID::null != mExperienceID)
- {
- const LLSD& experience = LLExperienceCache::instance().get(mExperienceID);
- std::stringstream desc;
-
- if(experience.isDefined())
- {
- setFromAvatarID(experience[LLExperienceCache::AGENT_ID]);
- desc << "Experience id: " << mExperienceID;
- }
- else
- {
- desc << "Unable to retrieve details for id: "<< mExperienceID;
- }
-
- LLUICtrl* details = getChild<LLUICtrl>("details_edit");
- details->setValue(desc.str());
- }
-}
-
-void LLFloaterReporter::getObjectInfo(const LLUUID& object_id)
-{
- // TODO --
- // 1 need to send to correct simulator if object is not
- // in same simulator as agent
- // 2 display info in widget window that gives feedback that
- // we have recorded the object info
- // 3 can pick avatar ==> might want to indicate when a picked
- // object is an avatar, attachment, or other category
-
- mObjectID = object_id;
-
- if (LLUUID::null != mObjectID)
- {
- // get object info for the user's benefit
- LLViewerObject* objectp = NULL;
- objectp = gObjectList.findObject( mObjectID );
- if (objectp)
- {
- if ( objectp->isAttachment() )
- {
- objectp = (LLViewerObject*)objectp->getRoot();
- mObjectID = objectp->getID();
- }
-
- // correct the region and position information
- LLViewerRegion *regionp = objectp->getRegion();
- if (regionp)
- {
- getChild<LLUICtrl>("sim_field")->setValue(regionp->getName());
- LLVector3d global_pos;
- global_pos.setVec(objectp->getPositionRegion());
- setPosBox(global_pos);
- }
-
- if (objectp->isAvatar())
- {
- setFromAvatarID(mObjectID);
- }
- else
- {
- // we have to query the simulator for information
- // about this object
- LLMessageSystem* msg = gMessageSystem;
- U32 request_flags = COMPLAINT_REPORT_REQUEST;
- msg->newMessageFast(_PREHASH_RequestObjectPropertiesFamily);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_ObjectData);
- msg->addU32Fast(_PREHASH_RequestFlags, request_flags );
- msg->addUUIDFast(_PREHASH_ObjectID, mObjectID);
- LLViewerRegion* regionp = objectp->getRegion();
- msg->sendReliable( regionp->getHost() );
- }
- }
- }
-}
-
-void LLFloaterReporter::onClickSelectAbuser()
-{
- LLView * button = findChild<LLButton>("select_abuser", true);
-
- LLFloater * root_floater = gFloaterView->getParentFloater(this);
- LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLFloaterReporter::callbackAvatarID, this, _1, _2), false, true, false, root_floater->getName(), button);
- if (picker)
- {
- root_floater->addDependentFloater(picker);
- }
-}
-
-void LLFloaterReporter::callbackAvatarID(const uuid_vec_t& ids, const std::vector<LLAvatarName> names)
-{
- if (ids.empty() || names.empty()) return;
-
- getChild<LLUICtrl>("abuser_name_edit")->setValue(names[0].getCompleteName());
-
- mAbuserID = ids[0];
-
- refresh();
-
-}
-
-void LLFloaterReporter::setFromAvatarID(const LLUUID& avatar_id)
-{
- mAbuserID = mObjectID = avatar_id;
- std::string avatar_link = LLSLURL("agent", mObjectID, "inspect").getSLURLString();
- getChild<LLUICtrl>("owner_name")->setValue(avatar_link);
-
- if (mAvatarNameCacheConnection.connected())
- {
- mAvatarNameCacheConnection.disconnect();
- }
- mAvatarNameCacheConnection = LLAvatarNameCache::get(avatar_id, boost::bind(&LLFloaterReporter::onAvatarNameCache, this, _1, _2));
-}
-
-void LLFloaterReporter::onAvatarNameCache(const LLUUID& avatar_id, const LLAvatarName& av_name)
-{
- mAvatarNameCacheConnection.disconnect();
-
- if (mObjectID == avatar_id)
- {
- mOwnerName = av_name.getCompleteName();
- getChild<LLUICtrl>("object_name")->setValue(av_name.getCompleteName());
- getChild<LLUICtrl>("object_name")->setToolTip(av_name.getCompleteName());
- getChild<LLUICtrl>("abuser_name_edit")->setValue(av_name.getCompleteName());
- }
-}
-
-void LLFloaterReporter::requestAbuseCategoriesCoro(std::string url, LLHandle<LLFloater> handle)
-{
- LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
- LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
- httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("requestAbuseCategoriesCoro", httpPolicy));
- LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
-
- LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
-
- LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
- LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
-
- if (!status || !result.has("categories")) // success = httpResults["success"].asBoolean();
- {
- LL_WARNS() << "Error requesting Abuse Categories from capability: " << url << LL_ENDL;
- return;
- }
-
- if (handle.isDead())
- {
- // nothing to do
- return;
- }
-
- LLFloater* floater = handle.get();
- LLComboBox* combo = floater->getChild<LLComboBox>("category_combo");
- if (!combo)
- {
- LL_WARNS() << "categories category_combo not found!" << LL_ENDL;
- return;
- }
-
- //get selection (in case capability took a while)
- S32 selection = combo->getCurrentIndex();
-
- // Combobox should have a "Select category" element;
- // This is a bit of workaround since there is no proper and simple way to save array of
- // localizable strings in xml along with data (value). For now combobox is initialized along
- // with placeholders, and first element is "Select category" which we want to keep, so remove
- // everything but first element.
- // Todo: once sim with capability fully releases, just remove this string and all unnecessary
- // items from combobox since they will be obsolete (or depending on situation remake this to
- // something better, for example move "Select category" to separate string)
- while (combo->remove(1));
-
- LLSD contents = result["categories"];
-
- LLSD::array_iterator i = contents.beginArray();
- LLSD::array_iterator iEnd = contents.endArray();
- for (; i != iEnd; ++i)
- {
- const LLSD &message_data(*i);
- std::string label = message_data["description_localized"];
- combo->add(label, message_data["category"]);
- }
-
- //restore selection
- combo->selectNthItem(selection);
-}
-
-// static
-void LLFloaterReporter::onClickSend(void *userdata)
-{
- LLFloaterReporter *self = (LLFloaterReporter *)userdata;
-
- if (self->mPicking)
- {
- closePickTool(self);
- }
-
- if(self->validateReport())
- {
-
- const int IP_CONTENT_REMOVAL = 66;
- const int IP_PERMISSONS_EXPLOIT = 37;
- LLComboBox* combo = self->getChild<LLComboBox>( "category_combo");
- int category_value = combo->getSelectedValue().asInteger();
-
- if ( ! self->mCopyrightWarningSeen )
- {
-
- std::string details_lc = self->getChild<LLUICtrl>("details_edit")->getValue().asString();
- LLStringUtil::toLower( details_lc );
- std::string summary_lc = self->getChild<LLUICtrl>("summary_edit")->getValue().asString();
- LLStringUtil::toLower( summary_lc );
- if ( details_lc.find( "copyright" ) != std::string::npos ||
- summary_lc.find( "copyright" ) != std::string::npos ||
- category_value == IP_CONTENT_REMOVAL ||
- category_value == IP_PERMISSONS_EXPLOIT)
- {
- LLNotificationsUtil::add("HelpReportAbuseContainsCopyright");
- self->mCopyrightWarningSeen = true;
- return;
- }
- }
- else if (category_value == IP_CONTENT_REMOVAL)
- {
- // IP_CONTENT_REMOVAL *always* shows the dialog -
- // ergo you can never send that abuse report type.
- LLNotificationsUtil::add("HelpReportAbuseContainsCopyright");
- return;
- }
-
- LLUploadDialog::modalUploadDialog(LLTrans::getString("uploading_abuse_report"));
- // *TODO don't upload image if checkbox isn't checked
- std::string url = gAgent.getRegionCapability("SendUserReport");
- std::string sshot_url = gAgent.getRegionCapability("SendUserReportWithScreenshot");
- if(!url.empty() || !sshot_url.empty())
- {
- self->sendReportViaCaps(url, sshot_url, self->gatherReport());
- LLNotificationsUtil::add("HelpReportAbuseConfirm");
- self->closeFloater();
- }
- else
- {
- self->getChildView("send_btn")->setEnabled(false);
- self->getChildView("cancel_btn")->setEnabled(false);
- // the callback from uploading the image calls sendReportViaLegacy()
- self->uploadImage();
- }
- }
-}
-
-
-// static
-void LLFloaterReporter::onClickCancel(void *userdata)
-{
- LLFloaterReporter *self = (LLFloaterReporter *)userdata;
-
- // reset flag in case the next report also contains this text
- self->mCopyrightWarningSeen = false;
-
- if (self->mPicking)
- {
- closePickTool(self);
- }
- self->closeFloater();
-}
-
-
-// static
-void LLFloaterReporter::onClickObjPicker(void *userdata)
-{
- LLFloaterReporter *self = (LLFloaterReporter *)userdata;
- LLToolObjPicker::getInstance()->setExitCallback(LLFloaterReporter::closePickTool, self);
- LLToolMgr::getInstance()->setTransientTool(LLToolObjPicker::getInstance());
- self->mPicking = true;
- self->getChild<LLUICtrl>("object_name")->setValue(LLStringUtil::null);
- self->getChild<LLUICtrl>("owner_name")->setValue(LLStringUtil::null);
- self->mOwnerName = LLStringUtil::null;
- LLButton* pick_btn = self->getChild<LLButton>("pick_btn");
- if (pick_btn) pick_btn->setToggleState(true);
-}
-
-
-// static
-void LLFloaterReporter::closePickTool(void *userdata)
-{
- LLFloaterReporter *self = (LLFloaterReporter *)userdata;
-
- LLUUID object_id = LLToolObjPicker::getInstance()->getObjectID();
- self->getObjectInfo(object_id);
-
- LLToolMgr::getInstance()->clearTransientTool();
- self->mPicking = false;
- LLButton* pick_btn = self->getChild<LLButton>("pick_btn");
- if (pick_btn) pick_btn->setToggleState(false);
-}
-
-
-// static
-void LLFloaterReporter::showFromMenu(EReportType report_type)
-{
- if (COMPLAINT_REPORT != report_type)
- {
- LL_WARNS() << "Unknown LLViewerReporter type : " << report_type << LL_ENDL;
- return;
- }
- LLFloaterReporter* reporter_floater = LLFloaterReg::findTypedInstance<LLFloaterReporter>("reporter");
- if(reporter_floater && reporter_floater->isInVisibleChain())
- {
- gSavedPerAccountSettings.setBOOL("PreviousScreenshotForReport", false);
- }
- reporter_floater = LLFloaterReg::showTypedInstance<LLFloaterReporter>("reporter", LLSD());
- if (reporter_floater)
- {
- reporter_floater->setReportType(report_type);
- }
-}
-
-// static
-void LLFloaterReporter::show(const LLUUID& object_id, const std::string& avatar_name, const LLUUID& experience_id)
-{
- LLFloaterReporter* reporter_floater = LLFloaterReg::findTypedInstance<LLFloaterReporter>("reporter");
- if(reporter_floater && reporter_floater->isInVisibleChain())
- {
- gSavedPerAccountSettings.setBOOL("PreviousScreenshotForReport", false);
- }
- reporter_floater = LLFloaterReg::showTypedInstance<LLFloaterReporter>("reporter");
- if (avatar_name.empty())
- {
- // Request info for this object
- reporter_floater->getObjectInfo(object_id);
- }
- else
- {
- reporter_floater->setFromAvatarID(object_id);
- }
- if(experience_id.notNull())
- {
- reporter_floater->getExperienceInfo(experience_id);
- }
-
- // Need to deselect on close
- reporter_floater->mDeselectOnClose = true;
-}
-
-
-
-void LLFloaterReporter::showFromExperience( const LLUUID& experience_id )
-{
- LLFloaterReporter* reporter_floater = LLFloaterReg::findTypedInstance<LLFloaterReporter>("reporter");
- if(reporter_floater && reporter_floater->isInVisibleChain())
- {
- gSavedPerAccountSettings.setBOOL("PreviousScreenshotForReport", false);
- }
- reporter_floater = LLFloaterReg::showTypedInstance<LLFloaterReporter>("reporter");
- reporter_floater->getExperienceInfo(experience_id);
-
- // Need to deselect on close
- reporter_floater->mDeselectOnClose = true;
-}
-
-
-// static
-void LLFloaterReporter::showFromObject(const LLUUID& object_id, const LLUUID& experience_id)
-{
- show(object_id, LLStringUtil::null, experience_id);
-}
-
-// static
-void LLFloaterReporter::showFromAvatar(const LLUUID& avatar_id, const std::string avatar_name)
-{
- show(avatar_id, avatar_name);
-}
-
-// static
-void LLFloaterReporter::showFromChat(const LLUUID& avatar_id, const std::string& avatar_name, const std::string& time, const std::string& description)
-{
- show(avatar_id, avatar_name);
-
- LLStringUtil::format_map_t args;
- args["[MSG_TIME]"] = time;
- args["[MSG_DESCRIPTION]"] = description;
-
- LLFloaterReporter *self = LLFloaterReg::findTypedInstance<LLFloaterReporter>("reporter");
- if (self)
- {
- std::string description = self->getString("chat_report_format", args);
- self->getChild<LLUICtrl>("details_edit")->setValue(description);
- }
-}
-
-void LLFloaterReporter::setPickedObjectProperties(const std::string& object_name, const std::string& owner_name, const LLUUID owner_id)
-{
- getChild<LLUICtrl>("object_name")->setValue(object_name);
- std::string owner_link =
- LLSLURL("agent", owner_id, "inspect").getSLURLString();
- getChild<LLUICtrl>("owner_name")->setValue(owner_link);
- getChild<LLUICtrl>("abuser_name_edit")->setValue(owner_name);
- mAbuserID = owner_id;
- mOwnerName = owner_name;
-}
-
-
-bool LLFloaterReporter::validateReport()
-{
- // Ensure user selected a category from the list
- LLSD category_sd = getChild<LLUICtrl>("category_combo")->getValue();
- U8 category = (U8)category_sd.asInteger();
- if (category == 0)
- {
- LLNotificationsUtil::add("HelpReportAbuseSelectCategory");
- return false;
- }
-
-
- if ( getChild<LLUICtrl>("abuser_name_edit")->getValue().asString().empty() )
- {
- LLNotificationsUtil::add("HelpReportAbuseAbuserNameEmpty");
- return false;
- };
-
- if ( getChild<LLUICtrl>("abuse_location_edit")->getValue().asString().empty() )
- {
- LLNotificationsUtil::add("HelpReportAbuseAbuserLocationEmpty");
- return false;
- };
-
- if ( getChild<LLUICtrl>("abuse_location_edit")->getValue().asString().empty() )
- {
- LLNotificationsUtil::add("HelpReportAbuseAbuserLocationEmpty");
- return false;
- };
-
-
- if ( getChild<LLUICtrl>("summary_edit")->getValue().asString().empty() )
- {
- LLNotificationsUtil::add("HelpReportAbuseSummaryEmpty");
- return false;
- };
-
- if ( getChild<LLUICtrl>("details_edit")->getValue().asString() == mDefaultSummary )
- {
- LLNotificationsUtil::add("HelpReportAbuseDetailsEmpty");
- return false;
- };
- return true;
-}
-
-LLSD LLFloaterReporter::gatherReport()
-{
- LLViewerRegion *regionp = gAgent.getRegion();
- if (!regionp) return LLSD(); // *TODO handle this failure case more gracefully
-
- // reset flag in case the next report also contains this text
- mCopyrightWarningSeen = false;
-
- std::ostringstream summary;
- if (!LLGridManager::getInstance()->isInProductionGrid())
- {
- summary << "Preview ";
- }
-
- std::string category_name;
- LLComboBox* combo = getChild<LLComboBox>( "category_combo");
- if (combo)
- {
- category_name = combo->getSelectedItemLabel(); // want label, not value
- }
-
-#if LL_WINDOWS
- const char* platform = "Win";
-#elif LL_DARWIN
- const char* platform = "Mac";
-#elif LL_LINUX
- const char* platform = "Lnx";
-#else
- const char* platform = "???";
-#endif
-
-
-
- summary << ""
- << " |" << regionp->getName() << "|" // region reporter is currently in.
- << " (" << getChild<LLUICtrl>("abuse_location_edit")->getValue().asString() << ")" // region abuse occured in (freeform text - no LLRegionPicker tool)
- << " [" << category_name << "] " // updated category
- << " {" << getChild<LLUICtrl>("abuser_name_edit")->getValue().asString() << "} " // name of abuse entered in report (chosen using LLAvatarPicker)
- << " \"" << getChild<LLUICtrl>("summary_edit")->getValue().asString() << "\""; // summary as entered
-
-
- std::ostringstream details;
-
- details << "V" << LLVersionInfo::instance().getVersion() << std::endl << std::endl; // client version moved to body of email for abuse reports
-
- std::string object_name = getChild<LLUICtrl>("object_name")->getValue().asString();
- if (!object_name.empty() && !mOwnerName.empty())
- {
- details << "Object: " << object_name << "\n";
- details << "Owner: " << mOwnerName << "\n";
- }
-
-
- details << "Abuser name: " << getChild<LLUICtrl>("abuser_name_edit")->getValue().asString() << " \n";
- details << "Abuser location: " << getChild<LLUICtrl>("abuse_location_edit")->getValue().asString() << " \n";
-
- details << getChild<LLUICtrl>("details_edit")->getValue().asString();
-
- std::string version_string;
- version_string = llformat(
- "%s %s %s %s %s",
- LLVersionInfo::instance().getShortVersion().c_str(),
- platform,
- gSysCPU.getFamily().c_str(),
- gGLManager.mGLRenderer.c_str(),
- gGLManager.mDriverVersionVendorString.c_str());
-
- // only send a screenshot ID if we're asked to and the email is
- // going to LL - Estate Owners cannot see the screenshot asset
- LLUUID screenshot_id = LLUUID::null;
- screenshot_id = getChild<LLUICtrl>("screenshot")->getValue();
-
- LLSD report = LLSD::emptyMap();
- report["report-type"] = (U8) mReportType;
- report["category"] = getChild<LLUICtrl>("category_combo")->getValue();
- report["position"] = mPosition.getValue();
- report["check-flags"] = (U8)0; // this is not used
- report["screenshot-id"] = screenshot_id;
- report["object-id"] = mObjectID;
- report["abuser-id"] = mAbuserID;
- report["abuse-region-name"] = "";
- report["abuse-region-id"] = LLUUID::null;
- report["summary"] = summary.str();
- report["version-string"] = version_string;
- report["details"] = details.str();
- return report;
-}
-
-void LLFloaterReporter::sendReportViaLegacy(const LLSD & report)
-{
- LLViewerRegion *regionp = gAgent.getRegion();
- if (!regionp) return;
- LLMessageSystem *msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_UserReport);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-
- msg->nextBlockFast(_PREHASH_ReportData);
- msg->addU8Fast(_PREHASH_ReportType, report["report-type"].asInteger());
- msg->addU8(_PREHASH_Category, report["category"].asInteger());
- msg->addVector3Fast(_PREHASH_Position, LLVector3(report["position"]));
- msg->addU8Fast(_PREHASH_CheckFlags, report["check-flags"].asInteger());
- msg->addUUIDFast(_PREHASH_ScreenshotID, report["screenshot-id"].asUUID());
- msg->addUUIDFast(_PREHASH_ObjectID, report["object-id"].asUUID());
- msg->addUUID("AbuserID", report["abuser-id"].asUUID());
- msg->addString("AbuseRegionName", report["abuse-region-name"].asString());
- msg->addUUID("AbuseRegionID", report["abuse-region-id"].asUUID());
-
- msg->addStringFast(_PREHASH_Summary, report["summary"].asString());
- msg->addString("VersionString", report["version-string"]);
- msg->addStringFast(_PREHASH_Details, report["details"] );
-
- msg->sendReliable(regionp->getHost());
-}
-
-void LLFloaterReporter::finishedARPost(const LLSD &)
-{
- LLUploadDialog::modalUploadFinished();
-
-}
-
-void LLFloaterReporter::sendReportViaCaps(std::string url, std::string sshot_url, const LLSD& report)
-{
- if(!sshot_url.empty())
- {
- // try to upload screenshot
- LLResourceUploadInfo::ptr_t uploadInfo(new LLARScreenShotUploader(report, mResourceDatap->mAssetInfo.mUuid, mResourceDatap->mAssetInfo.mType));
- LLViewerAssetUpload::EnqueueInventoryUpload(sshot_url, uploadInfo);
- }
- else
- {
- LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t proc = boost::bind(&LLFloaterReporter::finishedARPost, _1);
- LLUploadDialog::modalUploadDialog("Abuse Report");
- LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, report, proc, proc);
- }
-}
-
-void LLFloaterReporter::takeScreenshot(bool use_prev_screenshot)
-{
- gSavedPerAccountSettings.setBOOL("PreviousScreenshotForReport", true);
- if(!use_prev_screenshot)
- {
- std::string screenshot_filename(gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + SCREEN_PREV_FILENAME);
- LLPointer<LLImagePNG> png_image = new LLImagePNG;
- if(png_image->encode(mImageRaw, 0.0f))
- {
- png_image->save(screenshot_filename);
- }
- }
- else
- {
- mImageRaw = mPrevImageRaw;
- }
-
- LLPointer<LLImageJ2C> upload_data = LLViewerTextureList::convertToUploadFile(mImageRaw);
-
- // create a resource data
- mResourceDatap->mInventoryType = LLInventoryType::IT_NONE;
- mResourceDatap->mNextOwnerPerm = 0; // not used
- mResourceDatap->mExpectedUploadCost = 0; // we expect that abuse screenshots are free
- mResourceDatap->mAssetInfo.mTransactionID.generate();
- mResourceDatap->mAssetInfo.mUuid = mResourceDatap->mAssetInfo.mTransactionID.makeAssetID(gAgent.getSecureSessionID());
-
- if (COMPLAINT_REPORT == mReportType)
- {
- mResourceDatap->mAssetInfo.mType = LLAssetType::AT_TEXTURE;
- mResourceDatap->mPreferredLocation = LLFolderType::EType(LLResourceData::INVALID_LOCATION);
- }
- else
- {
- LL_WARNS() << "Unknown LLFloaterReporter type" << LL_ENDL;
- }
- mResourceDatap->mAssetInfo.mCreatorID = gAgentID;
- mResourceDatap->mAssetInfo.setName("screenshot_name");
- mResourceDatap->mAssetInfo.setDescription("screenshot_descr");
-
- // store in cache
- LLFileSystem j2c_file(mResourceDatap->mAssetInfo.mUuid, mResourceDatap->mAssetInfo.mType, LLFileSystem::WRITE);
- j2c_file.write(upload_data->getData(), upload_data->getDataSize());
-
- // store in the image list so it doesn't try to fetch from the server
- LLPointer<LLViewerFetchedTexture> image_in_list =
- LLViewerTextureManager::getFetchedTexture(mResourceDatap->mAssetInfo.mUuid);
- image_in_list->createGLTexture(0, mImageRaw, 0, true, LLGLTexture::OTHER);
-
- // the texture picker then uses that texture
- LLTextureCtrl* texture = getChild<LLTextureCtrl>("screenshot");
- if (texture)
- {
- texture->setImageAssetID(mResourceDatap->mAssetInfo.mUuid);
- texture->setDefaultImageAssetID(mResourceDatap->mAssetInfo.mUuid);
- texture->setCaption(getString("Screenshot"));
- }
-}
-
-void LLFloaterReporter::takeNewSnapshot()
-{
- childSetEnabled("send_btn", true);
- mImageRaw = new LLImageRaw;
- const S32 IMAGE_WIDTH = 1024;
- const S32 IMAGE_HEIGHT = 768;
-
- // Take a screenshot, but don't draw this floater.
- setVisible(false);
- if (!gViewerWindow->rawSnapshot(mImageRaw,IMAGE_WIDTH, IMAGE_HEIGHT, true, false, true /*UI*/, true, false))
- {
- LL_WARNS() << "Unable to take screenshot" << LL_ENDL;
- setVisible(true);
- return;
- }
- setVisible(true);
-
- if(gSavedPerAccountSettings.getBOOL("PreviousScreenshotForReport"))
- {
- std::string screenshot_filename(gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + SCREEN_PREV_FILENAME);
- mPrevImageRaw = new LLImageRaw;
- LLPointer<LLImagePNG> start_image_png = new LLImagePNG;
- if(start_image_png->load(screenshot_filename))
- {
- if (start_image_png->decode(mPrevImageRaw, 0.0f))
- {
- LLNotificationsUtil::add("LoadPreviousReportScreenshot", LLSD(), LLSD(), boost::bind(&LLFloaterReporter::onLoadScreenshotDialog,this, _1, _2));
- return;
- }
- }
- }
- takeScreenshot();
-}
-
-
-void LLFloaterReporter::onOpen(const LLSD& key)
-{
- childSetEnabled("send_btn", false);
- //Time delay to avoid UI artifacts. MAINT-7067
- mSnapshotTimer.start();
-}
-
-void LLFloaterReporter::onLoadScreenshotDialog(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- takeScreenshot(option == 0);
-}
-
-void LLFloaterReporter::uploadImage()
-{
- LL_INFOS() << "*** Uploading: " << LL_ENDL;
- LL_INFOS() << "Type: " << LLAssetType::lookup(mResourceDatap->mAssetInfo.mType) << LL_ENDL;
- LL_INFOS() << "UUID: " << mResourceDatap->mAssetInfo.mUuid << LL_ENDL;
- LL_INFOS() << "Name: " << mResourceDatap->mAssetInfo.getName() << LL_ENDL;
- LL_INFOS() << "Desc: " << mResourceDatap->mAssetInfo.getDescription() << LL_ENDL;
-
- gAssetStorage->storeAssetData(mResourceDatap->mAssetInfo.mTransactionID,
- mResourceDatap->mAssetInfo.mType,
- LLFloaterReporter::uploadDoneCallback,
- (void*)mResourceDatap, true);
-}
-
-
-// static
-void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data, S32 result, LLExtStat ext_status) // StoreAssetData callback (fixed)
-{
- LLUploadDialog::modalUploadFinished();
-
- LLResourceData* data = (LLResourceData*)user_data;
-
- if(result < 0)
- {
- LLSD args;
- args["REASON"] = std::string(LLAssetStorage::getErrorString(result));
- LLNotificationsUtil::add("ErrorUploadingReportScreenshot", args);
-
- std::string err_msg("There was a problem uploading a report screenshot");
- err_msg += " due to the following reason: " + args["REASON"].asString();
- LL_WARNS() << err_msg << LL_ENDL;
- return;
- }
-
- if (data->mPreferredLocation != LLResourceData::INVALID_LOCATION)
- {
- LL_WARNS() << "Unknown report type : " << data->mPreferredLocation << LL_ENDL;
- }
-
- LLFloaterReporter *self = LLFloaterReg::findTypedInstance<LLFloaterReporter>("reporter");
- if (self)
- {
- self->mScreenID = uuid;
- LL_INFOS() << "Got screen shot " << uuid << LL_ENDL;
- self->sendReportViaLegacy(self->gatherReport());
- LLNotificationsUtil::add("HelpReportAbuseConfirm");
- self->closeFloater();
- }
-}
-
-
-void LLFloaterReporter::setPosBox(const LLVector3d &pos)
-{
- mPosition.setVec(pos);
- std::string pos_string = llformat("{%.1f, %.1f, %.1f}",
- mPosition.mV[VX],
- mPosition.mV[VY],
- mPosition.mV[VZ]);
- getChild<LLUICtrl>("pos_field")->setValue(pos_string);
-}
-
-void LLFloaterReporter::onClose(bool app_quitting)
-{
- mSnapshotTimer.stop();
- gSavedPerAccountSettings.setBOOL("PreviousScreenshotForReport", app_quitting);
-}
+/** + * @file llfloaterreporter.cpp + * @brief Abuse reports. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +// self include +#include "llfloaterreporter.h" + +#include <sstream> + +// linden library includes +#include "llassetstorage.h" +#include "llavatarnamecache.h" +#include "llcachename.h" +#include "llcallbacklist.h" +#include "llcheckboxctrl.h" +#include "llfontgl.h" +#include "llimagepng.h" +#include "llimagej2c.h" +#include "llinventory.h" +#include "llnotificationsutil.h" +#include "llstring.h" +#include "llsys.h" +#include "llfilesystem.h" +#include "mean_collision_data.h" +#include "message.h" +#include "v3math.h" + +// viewer project includes +#include "llagent.h" +#include "llbutton.h" +#include "llfloaterreg.h" +#include "lltexturectrl.h" +#include "lltexteditor.h" +#include "llscrolllistctrl.h" +#include "lldispatcher.h" +#include "llviewerobject.h" +#include "llviewerregion.h" +#include "llcombobox.h" +#include "lltooldraganddrop.h" +#include "lluiconstants.h" +#include "lluploaddialog.h" +#include "llcallingcard.h" +#include "llviewerobjectlist.h" +#include "lltoolobjpicker.h" +#include "lltoolmgr.h" +#include "llresourcedata.h" // for LLResourceData +#include "llslurl.h" +#include "llviewerwindow.h" +#include "llviewertexturelist.h" +#include "llworldmap.h" +#include "llfilepicker.h" +#include "llfloateravatarpicker.h" +#include "lldir.h" +#include "llselectmgr.h" +#include "llversioninfo.h" +#include "lluictrlfactory.h" +#include "llviewercontrol.h" +#include "llviewernetwork.h" + +#include "llagentui.h" + +#include "lltrans.h" +#include "llexperiencecache.h" + +#include "llcorehttputil.h" +#include "llviewerassetupload.h" + +const std::string SCREEN_PREV_FILENAME = "screen_report_last.png"; + +//========================================================================= +//----------------------------------------------------------------------------- +// Support classes +//----------------------------------------------------------------------------- +class LLARScreenShotUploader : public LLResourceUploadInfo +{ +public: + LLARScreenShotUploader(LLSD report, LLUUID assetId, LLAssetType::EType assetType); + + virtual LLSD prepareUpload(); + virtual LLSD generatePostBody(); + virtual LLUUID finishUpload(LLSD &result); + + virtual bool showInventoryPanel() const { return false; } + virtual std::string getDisplayName() const { return "Abuse Report"; } + +private: + + LLSD mReport; +}; + +LLARScreenShotUploader::LLARScreenShotUploader(LLSD report, LLUUID assetId, LLAssetType::EType assetType) : + LLResourceUploadInfo(assetId, assetType, "Abuse Report"), + mReport(report) +{ +} + +LLSD LLARScreenShotUploader::prepareUpload() +{ + return LLSD().with("success", LLSD::Boolean(true)); +} + +LLSD LLARScreenShotUploader::generatePostBody() +{ // The report was pregenerated and passed in the constructor. + return mReport; +} + +LLUUID LLARScreenShotUploader::finishUpload(LLSD &result) +{ + /* *TODO$: Report success or failure. Carried over from previous todo on responder*/ + return LLUUID::null; +} + + +//========================================================================= +//----------------------------------------------------------------------------- +// Globals +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Member functions +//----------------------------------------------------------------------------- + +LLFloaterReporter::LLFloaterReporter(const LLSD& key) +: LLFloater(key), + mReportType(COMPLAINT_REPORT), + mObjectID(), + mScreenID(), + mAbuserID(), + mOwnerName(), + mDeselectOnClose( false ), + mPicking( false), + mPosition(), + mCopyrightWarningSeen( false ), + mResourceDatap(new LLResourceData()), + mAvatarNameCacheConnection() +{ + gIdleCallbacks.addFunction(onIdle, this); +} + +// virtual +bool LLFloaterReporter::postBuild() +{ + LLSLURL slurl; + LLAgentUI::buildSLURL(slurl); + getChild<LLUICtrl>("abuse_location_edit")->setValue(slurl.getSLURLString()); + + enableControls(true); + + // convert the position to a string + LLVector3d pos = gAgent.getPositionGlobal(); + LLViewerRegion *regionp = gAgent.getRegion(); + if (regionp) + { + getChild<LLUICtrl>("sim_field")->setValue(regionp->getName()); + pos -= regionp->getOriginGlobal(); + } + setPosBox(pos); + + // Default text to be blank + getChild<LLUICtrl>("object_name")->setValue(LLStringUtil::null); + getChild<LLUICtrl>("owner_name")->setValue(LLStringUtil::null); + mOwnerName = LLStringUtil::null; + + getChild<LLUICtrl>("summary_edit")->setFocus(true); + + mDefaultSummary = getChild<LLUICtrl>("details_edit")->getValue().asString(); + + // abuser name is selected from a list + LLUICtrl* le = getChild<LLUICtrl>("abuser_name_edit"); + le->setEnabled( false ); + + setPosBox((LLVector3d)mPosition.getValue()); + LLButton* pick_btn = getChild<LLButton>("pick_btn"); + pick_btn->setImages(std::string("tool_face.tga"), + std::string("tool_face_active.tga") ); + childSetAction("pick_btn", onClickObjPicker, this); + + childSetAction("select_abuser", boost::bind(&LLFloaterReporter::onClickSelectAbuser, this)); + + childSetAction("send_btn", onClickSend, this); + childSetAction("cancel_btn", onClickCancel, this); + + // grab the user's name + std::string reporter = LLSLURL("agent", gAgent.getID(), "inspect").getSLURLString(); + getChild<LLUICtrl>("reporter_field")->setValue(reporter); + + // request categories + if (gAgent.getRegion() + && gAgent.getRegion()->capabilitiesReceived()) + { + std::string cap_url = gAgent.getRegionCapability("AbuseCategories"); + + if (!cap_url.empty()) + { + std::string lang = gSavedSettings.getString("Language"); + if (lang != "default" && !lang.empty()) + { + cap_url += "?lc="; + cap_url += lang; + } + LLCoros::instance().launch("LLFloaterReporter::requestAbuseCategoriesCoro", + boost::bind(LLFloaterReporter::requestAbuseCategoriesCoro, cap_url, this->getHandle())); + } + } + + center(); + + return true; +} + +// virtual +LLFloaterReporter::~LLFloaterReporter() +{ + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + gIdleCallbacks.deleteFunction(onIdle, this); + + // child views automatically deleted + mObjectID = LLUUID::null; + + if (mPicking) + { + closePickTool(this); + } + + mPosition.setVec(0.0f, 0.0f, 0.0f); + + delete mResourceDatap; +} + +void LLFloaterReporter::onIdle(void* user_data) +{ + LLFloaterReporter* floater_reporter = (LLFloaterReporter*)user_data; + if (floater_reporter) + { + static LLCachedControl<F32> screenshot_delay(gSavedSettings, "AbuseReportScreenshotDelay"); + if (floater_reporter->mSnapshotTimer.getStarted() && floater_reporter->mSnapshotTimer.getElapsedTimeF32() > screenshot_delay) + { + floater_reporter->mSnapshotTimer.stop(); + floater_reporter->takeNewSnapshot(); + } + } +} + +void LLFloaterReporter::enableControls(bool enable) +{ + getChildView("category_combo")->setEnabled(enable); + getChildView("chat_check")->setEnabled(enable); + getChildView("screenshot")->setEnabled(false); + getChildView("pick_btn")->setEnabled(enable); + getChildView("summary_edit")->setEnabled(enable); + getChildView("details_edit")->setEnabled(enable); + getChildView("send_btn")->setEnabled(enable); + getChildView("cancel_btn")->setEnabled(enable); +} + +void LLFloaterReporter::getExperienceInfo(const LLUUID& experience_id) +{ + mExperienceID = experience_id; + + if (LLUUID::null != mExperienceID) + { + const LLSD& experience = LLExperienceCache::instance().get(mExperienceID); + std::stringstream desc; + + if(experience.isDefined()) + { + setFromAvatarID(experience[LLExperienceCache::AGENT_ID]); + desc << "Experience id: " << mExperienceID; + } + else + { + desc << "Unable to retrieve details for id: "<< mExperienceID; + } + + LLUICtrl* details = getChild<LLUICtrl>("details_edit"); + details->setValue(desc.str()); + } +} + +void LLFloaterReporter::getObjectInfo(const LLUUID& object_id) +{ + // TODO -- + // 1 need to send to correct simulator if object is not + // in same simulator as agent + // 2 display info in widget window that gives feedback that + // we have recorded the object info + // 3 can pick avatar ==> might want to indicate when a picked + // object is an avatar, attachment, or other category + + mObjectID = object_id; + + if (LLUUID::null != mObjectID) + { + // get object info for the user's benefit + LLViewerObject* objectp = NULL; + objectp = gObjectList.findObject( mObjectID ); + if (objectp) + { + if ( objectp->isAttachment() ) + { + objectp = (LLViewerObject*)objectp->getRoot(); + mObjectID = objectp->getID(); + } + + // correct the region and position information + LLViewerRegion *regionp = objectp->getRegion(); + if (regionp) + { + getChild<LLUICtrl>("sim_field")->setValue(regionp->getName()); + LLVector3d global_pos; + global_pos.setVec(objectp->getPositionRegion()); + setPosBox(global_pos); + } + + if (objectp->isAvatar()) + { + setFromAvatarID(mObjectID); + } + else + { + // we have to query the simulator for information + // about this object + LLMessageSystem* msg = gMessageSystem; + U32 request_flags = COMPLAINT_REPORT_REQUEST; + msg->newMessageFast(_PREHASH_RequestObjectPropertiesFamily); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_RequestFlags, request_flags ); + msg->addUUIDFast(_PREHASH_ObjectID, mObjectID); + LLViewerRegion* regionp = objectp->getRegion(); + msg->sendReliable( regionp->getHost() ); + } + } + } +} + +void LLFloaterReporter::onClickSelectAbuser() +{ + LLView * button = findChild<LLButton>("select_abuser", true); + + LLFloater * root_floater = gFloaterView->getParentFloater(this); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLFloaterReporter::callbackAvatarID, this, _1, _2), false, true, false, root_floater->getName(), button); + if (picker) + { + root_floater->addDependentFloater(picker); + } +} + +void LLFloaterReporter::callbackAvatarID(const uuid_vec_t& ids, const std::vector<LLAvatarName> names) +{ + if (ids.empty() || names.empty()) return; + + getChild<LLUICtrl>("abuser_name_edit")->setValue(names[0].getCompleteName()); + + mAbuserID = ids[0]; + + refresh(); + +} + +void LLFloaterReporter::setFromAvatarID(const LLUUID& avatar_id) +{ + mAbuserID = mObjectID = avatar_id; + std::string avatar_link = LLSLURL("agent", mObjectID, "inspect").getSLURLString(); + getChild<LLUICtrl>("owner_name")->setValue(avatar_link); + + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + mAvatarNameCacheConnection = LLAvatarNameCache::get(avatar_id, boost::bind(&LLFloaterReporter::onAvatarNameCache, this, _1, _2)); +} + +void LLFloaterReporter::onAvatarNameCache(const LLUUID& avatar_id, const LLAvatarName& av_name) +{ + mAvatarNameCacheConnection.disconnect(); + + if (mObjectID == avatar_id) + { + mOwnerName = av_name.getCompleteName(); + getChild<LLUICtrl>("object_name")->setValue(av_name.getCompleteName()); + getChild<LLUICtrl>("object_name")->setToolTip(av_name.getCompleteName()); + getChild<LLUICtrl>("abuser_name_edit")->setValue(av_name.getCompleteName()); + } +} + +void LLFloaterReporter::requestAbuseCategoriesCoro(std::string url, LLHandle<LLFloater> handle) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("requestAbuseCategoriesCoro", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + LLSD result = httpAdapter->getAndSuspend(httpRequest, url); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status || !result.has("categories")) // success = httpResults["success"].asBoolean(); + { + LL_WARNS() << "Error requesting Abuse Categories from capability: " << url << LL_ENDL; + return; + } + + if (handle.isDead()) + { + // nothing to do + return; + } + + LLFloater* floater = handle.get(); + LLComboBox* combo = floater->getChild<LLComboBox>("category_combo"); + if (!combo) + { + LL_WARNS() << "categories category_combo not found!" << LL_ENDL; + return; + } + + //get selection (in case capability took a while) + S32 selection = combo->getCurrentIndex(); + + // Combobox should have a "Select category" element; + // This is a bit of workaround since there is no proper and simple way to save array of + // localizable strings in xml along with data (value). For now combobox is initialized along + // with placeholders, and first element is "Select category" which we want to keep, so remove + // everything but first element. + // Todo: once sim with capability fully releases, just remove this string and all unnecessary + // items from combobox since they will be obsolete (or depending on situation remake this to + // something better, for example move "Select category" to separate string) + while (combo->remove(1)); + + LLSD contents = result["categories"]; + + LLSD::array_iterator i = contents.beginArray(); + LLSD::array_iterator iEnd = contents.endArray(); + for (; i != iEnd; ++i) + { + const LLSD &message_data(*i); + std::string label = message_data["description_localized"]; + combo->add(label, message_data["category"]); + } + + //restore selection + combo->selectNthItem(selection); +} + +// static +void LLFloaterReporter::onClickSend(void *userdata) +{ + LLFloaterReporter *self = (LLFloaterReporter *)userdata; + + if (self->mPicking) + { + closePickTool(self); + } + + if(self->validateReport()) + { + + const int IP_CONTENT_REMOVAL = 66; + const int IP_PERMISSONS_EXPLOIT = 37; + LLComboBox* combo = self->getChild<LLComboBox>( "category_combo"); + int category_value = combo->getSelectedValue().asInteger(); + + if ( ! self->mCopyrightWarningSeen ) + { + + std::string details_lc = self->getChild<LLUICtrl>("details_edit")->getValue().asString(); + LLStringUtil::toLower( details_lc ); + std::string summary_lc = self->getChild<LLUICtrl>("summary_edit")->getValue().asString(); + LLStringUtil::toLower( summary_lc ); + if ( details_lc.find( "copyright" ) != std::string::npos || + summary_lc.find( "copyright" ) != std::string::npos || + category_value == IP_CONTENT_REMOVAL || + category_value == IP_PERMISSONS_EXPLOIT) + { + LLNotificationsUtil::add("HelpReportAbuseContainsCopyright"); + self->mCopyrightWarningSeen = true; + return; + } + } + else if (category_value == IP_CONTENT_REMOVAL) + { + // IP_CONTENT_REMOVAL *always* shows the dialog - + // ergo you can never send that abuse report type. + LLNotificationsUtil::add("HelpReportAbuseContainsCopyright"); + return; + } + + LLUploadDialog::modalUploadDialog(LLTrans::getString("uploading_abuse_report")); + // *TODO don't upload image if checkbox isn't checked + std::string url = gAgent.getRegionCapability("SendUserReport"); + std::string sshot_url = gAgent.getRegionCapability("SendUserReportWithScreenshot"); + if(!url.empty() || !sshot_url.empty()) + { + self->sendReportViaCaps(url, sshot_url, self->gatherReport()); + LLNotificationsUtil::add("HelpReportAbuseConfirm"); + self->closeFloater(); + } + else + { + self->getChildView("send_btn")->setEnabled(false); + self->getChildView("cancel_btn")->setEnabled(false); + // the callback from uploading the image calls sendReportViaLegacy() + self->uploadImage(); + } + } +} + + +// static +void LLFloaterReporter::onClickCancel(void *userdata) +{ + LLFloaterReporter *self = (LLFloaterReporter *)userdata; + + // reset flag in case the next report also contains this text + self->mCopyrightWarningSeen = false; + + if (self->mPicking) + { + closePickTool(self); + } + self->closeFloater(); +} + + +// static +void LLFloaterReporter::onClickObjPicker(void *userdata) +{ + LLFloaterReporter *self = (LLFloaterReporter *)userdata; + LLToolObjPicker::getInstance()->setExitCallback(LLFloaterReporter::closePickTool, self); + LLToolMgr::getInstance()->setTransientTool(LLToolObjPicker::getInstance()); + self->mPicking = true; + self->getChild<LLUICtrl>("object_name")->setValue(LLStringUtil::null); + self->getChild<LLUICtrl>("owner_name")->setValue(LLStringUtil::null); + self->mOwnerName = LLStringUtil::null; + LLButton* pick_btn = self->getChild<LLButton>("pick_btn"); + if (pick_btn) pick_btn->setToggleState(true); +} + + +// static +void LLFloaterReporter::closePickTool(void *userdata) +{ + LLFloaterReporter *self = (LLFloaterReporter *)userdata; + + LLUUID object_id = LLToolObjPicker::getInstance()->getObjectID(); + self->getObjectInfo(object_id); + + LLToolMgr::getInstance()->clearTransientTool(); + self->mPicking = false; + LLButton* pick_btn = self->getChild<LLButton>("pick_btn"); + if (pick_btn) pick_btn->setToggleState(false); +} + + +// static +void LLFloaterReporter::showFromMenu(EReportType report_type) +{ + if (COMPLAINT_REPORT != report_type) + { + LL_WARNS() << "Unknown LLViewerReporter type : " << report_type << LL_ENDL; + return; + } + LLFloaterReporter* reporter_floater = LLFloaterReg::findTypedInstance<LLFloaterReporter>("reporter"); + if(reporter_floater && reporter_floater->isInVisibleChain()) + { + gSavedPerAccountSettings.setBOOL("PreviousScreenshotForReport", false); + } + reporter_floater = LLFloaterReg::showTypedInstance<LLFloaterReporter>("reporter", LLSD()); + if (reporter_floater) + { + reporter_floater->setReportType(report_type); + } +} + +// static +void LLFloaterReporter::show(const LLUUID& object_id, const std::string& avatar_name, const LLUUID& experience_id) +{ + LLFloaterReporter* reporter_floater = LLFloaterReg::findTypedInstance<LLFloaterReporter>("reporter"); + if(reporter_floater && reporter_floater->isInVisibleChain()) + { + gSavedPerAccountSettings.setBOOL("PreviousScreenshotForReport", false); + } + reporter_floater = LLFloaterReg::showTypedInstance<LLFloaterReporter>("reporter"); + if (avatar_name.empty()) + { + // Request info for this object + reporter_floater->getObjectInfo(object_id); + } + else + { + reporter_floater->setFromAvatarID(object_id); + } + if(experience_id.notNull()) + { + reporter_floater->getExperienceInfo(experience_id); + } + + // Need to deselect on close + reporter_floater->mDeselectOnClose = true; +} + + + +void LLFloaterReporter::showFromExperience( const LLUUID& experience_id ) +{ + LLFloaterReporter* reporter_floater = LLFloaterReg::findTypedInstance<LLFloaterReporter>("reporter"); + if(reporter_floater && reporter_floater->isInVisibleChain()) + { + gSavedPerAccountSettings.setBOOL("PreviousScreenshotForReport", false); + } + reporter_floater = LLFloaterReg::showTypedInstance<LLFloaterReporter>("reporter"); + reporter_floater->getExperienceInfo(experience_id); + + // Need to deselect on close + reporter_floater->mDeselectOnClose = true; +} + + +// static +void LLFloaterReporter::showFromObject(const LLUUID& object_id, const LLUUID& experience_id) +{ + show(object_id, LLStringUtil::null, experience_id); +} + +// static +void LLFloaterReporter::showFromAvatar(const LLUUID& avatar_id, const std::string avatar_name) +{ + show(avatar_id, avatar_name); +} + +// static +void LLFloaterReporter::showFromChat(const LLUUID& avatar_id, const std::string& avatar_name, const std::string& time, const std::string& description) +{ + show(avatar_id, avatar_name); + + LLStringUtil::format_map_t args; + args["[MSG_TIME]"] = time; + args["[MSG_DESCRIPTION]"] = description; + + LLFloaterReporter *self = LLFloaterReg::findTypedInstance<LLFloaterReporter>("reporter"); + if (self) + { + std::string description = self->getString("chat_report_format", args); + self->getChild<LLUICtrl>("details_edit")->setValue(description); + } +} + +void LLFloaterReporter::setPickedObjectProperties(const std::string& object_name, const std::string& owner_name, const LLUUID owner_id) +{ + getChild<LLUICtrl>("object_name")->setValue(object_name); + std::string owner_link = + LLSLURL("agent", owner_id, "inspect").getSLURLString(); + getChild<LLUICtrl>("owner_name")->setValue(owner_link); + getChild<LLUICtrl>("abuser_name_edit")->setValue(owner_name); + mAbuserID = owner_id; + mOwnerName = owner_name; +} + + +bool LLFloaterReporter::validateReport() +{ + // Ensure user selected a category from the list + LLSD category_sd = getChild<LLUICtrl>("category_combo")->getValue(); + U8 category = (U8)category_sd.asInteger(); + if (category == 0) + { + LLNotificationsUtil::add("HelpReportAbuseSelectCategory"); + return false; + } + + + if ( getChild<LLUICtrl>("abuser_name_edit")->getValue().asString().empty() ) + { + LLNotificationsUtil::add("HelpReportAbuseAbuserNameEmpty"); + return false; + }; + + if ( getChild<LLUICtrl>("abuse_location_edit")->getValue().asString().empty() ) + { + LLNotificationsUtil::add("HelpReportAbuseAbuserLocationEmpty"); + return false; + }; + + if ( getChild<LLUICtrl>("abuse_location_edit")->getValue().asString().empty() ) + { + LLNotificationsUtil::add("HelpReportAbuseAbuserLocationEmpty"); + return false; + }; + + + if ( getChild<LLUICtrl>("summary_edit")->getValue().asString().empty() ) + { + LLNotificationsUtil::add("HelpReportAbuseSummaryEmpty"); + return false; + }; + + if ( getChild<LLUICtrl>("details_edit")->getValue().asString() == mDefaultSummary ) + { + LLNotificationsUtil::add("HelpReportAbuseDetailsEmpty"); + return false; + }; + return true; +} + +LLSD LLFloaterReporter::gatherReport() +{ + LLViewerRegion *regionp = gAgent.getRegion(); + if (!regionp) return LLSD(); // *TODO handle this failure case more gracefully + + // reset flag in case the next report also contains this text + mCopyrightWarningSeen = false; + + std::ostringstream summary; + if (!LLGridManager::getInstance()->isInProductionGrid()) + { + summary << "Preview "; + } + + std::string category_name; + LLComboBox* combo = getChild<LLComboBox>( "category_combo"); + if (combo) + { + category_name = combo->getSelectedItemLabel(); // want label, not value + } + +#if LL_WINDOWS + const char* platform = "Win"; +#elif LL_DARWIN + const char* platform = "Mac"; +#elif LL_LINUX + const char* platform = "Lnx"; +#else + const char* platform = "???"; +#endif + + + + summary << "" + << " |" << regionp->getName() << "|" // region reporter is currently in. + << " (" << getChild<LLUICtrl>("abuse_location_edit")->getValue().asString() << ")" // region abuse occured in (freeform text - no LLRegionPicker tool) + << " [" << category_name << "] " // updated category + << " {" << getChild<LLUICtrl>("abuser_name_edit")->getValue().asString() << "} " // name of abuse entered in report (chosen using LLAvatarPicker) + << " \"" << getChild<LLUICtrl>("summary_edit")->getValue().asString() << "\""; // summary as entered + + + std::ostringstream details; + + details << "V" << LLVersionInfo::instance().getVersion() << std::endl << std::endl; // client version moved to body of email for abuse reports + + std::string object_name = getChild<LLUICtrl>("object_name")->getValue().asString(); + if (!object_name.empty() && !mOwnerName.empty()) + { + details << "Object: " << object_name << "\n"; + details << "Owner: " << mOwnerName << "\n"; + } + + + details << "Abuser name: " << getChild<LLUICtrl>("abuser_name_edit")->getValue().asString() << " \n"; + details << "Abuser location: " << getChild<LLUICtrl>("abuse_location_edit")->getValue().asString() << " \n"; + + details << getChild<LLUICtrl>("details_edit")->getValue().asString(); + + std::string version_string; + version_string = llformat( + "%s %s %s %s %s", + LLVersionInfo::instance().getShortVersion().c_str(), + platform, + gSysCPU.getFamily().c_str(), + gGLManager.mGLRenderer.c_str(), + gGLManager.mDriverVersionVendorString.c_str()); + + // only send a screenshot ID if we're asked to and the email is + // going to LL - Estate Owners cannot see the screenshot asset + LLUUID screenshot_id = LLUUID::null; + screenshot_id = getChild<LLUICtrl>("screenshot")->getValue(); + + LLSD report = LLSD::emptyMap(); + report["report-type"] = (U8) mReportType; + report["category"] = getChild<LLUICtrl>("category_combo")->getValue(); + report["position"] = mPosition.getValue(); + report["check-flags"] = (U8)0; // this is not used + report["screenshot-id"] = screenshot_id; + report["object-id"] = mObjectID; + report["abuser-id"] = mAbuserID; + report["abuse-region-name"] = ""; + report["abuse-region-id"] = LLUUID::null; + report["summary"] = summary.str(); + report["version-string"] = version_string; + report["details"] = details.str(); + return report; +} + +void LLFloaterReporter::sendReportViaLegacy(const LLSD & report) +{ + LLViewerRegion *regionp = gAgent.getRegion(); + if (!regionp) return; + LLMessageSystem *msg = gMessageSystem; + msg->newMessageFast(_PREHASH_UserReport); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + + msg->nextBlockFast(_PREHASH_ReportData); + msg->addU8Fast(_PREHASH_ReportType, report["report-type"].asInteger()); + msg->addU8(_PREHASH_Category, report["category"].asInteger()); + msg->addVector3Fast(_PREHASH_Position, LLVector3(report["position"])); + msg->addU8Fast(_PREHASH_CheckFlags, report["check-flags"].asInteger()); + msg->addUUIDFast(_PREHASH_ScreenshotID, report["screenshot-id"].asUUID()); + msg->addUUIDFast(_PREHASH_ObjectID, report["object-id"].asUUID()); + msg->addUUID("AbuserID", report["abuser-id"].asUUID()); + msg->addString("AbuseRegionName", report["abuse-region-name"].asString()); + msg->addUUID("AbuseRegionID", report["abuse-region-id"].asUUID()); + + msg->addStringFast(_PREHASH_Summary, report["summary"].asString()); + msg->addString("VersionString", report["version-string"]); + msg->addStringFast(_PREHASH_Details, report["details"] ); + + msg->sendReliable(regionp->getHost()); +} + +void LLFloaterReporter::finishedARPost(const LLSD &) +{ + LLUploadDialog::modalUploadFinished(); + +} + +void LLFloaterReporter::sendReportViaCaps(std::string url, std::string sshot_url, const LLSD& report) +{ + if(!sshot_url.empty()) + { + // try to upload screenshot + LLResourceUploadInfo::ptr_t uploadInfo(new LLARScreenShotUploader(report, mResourceDatap->mAssetInfo.mUuid, mResourceDatap->mAssetInfo.mType)); + LLViewerAssetUpload::EnqueueInventoryUpload(sshot_url, uploadInfo); + } + else + { + LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t proc = boost::bind(&LLFloaterReporter::finishedARPost, _1); + LLUploadDialog::modalUploadDialog("Abuse Report"); + LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, report, proc, proc); + } +} + +void LLFloaterReporter::takeScreenshot(bool use_prev_screenshot) +{ + gSavedPerAccountSettings.setBOOL("PreviousScreenshotForReport", true); + if(!use_prev_screenshot) + { + std::string screenshot_filename(gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + SCREEN_PREV_FILENAME); + LLPointer<LLImagePNG> png_image = new LLImagePNG; + if(png_image->encode(mImageRaw, 0.0f)) + { + png_image->save(screenshot_filename); + } + } + else + { + mImageRaw = mPrevImageRaw; + } + + LLPointer<LLImageJ2C> upload_data = LLViewerTextureList::convertToUploadFile(mImageRaw); + + // create a resource data + mResourceDatap->mInventoryType = LLInventoryType::IT_NONE; + mResourceDatap->mNextOwnerPerm = 0; // not used + mResourceDatap->mExpectedUploadCost = 0; // we expect that abuse screenshots are free + mResourceDatap->mAssetInfo.mTransactionID.generate(); + mResourceDatap->mAssetInfo.mUuid = mResourceDatap->mAssetInfo.mTransactionID.makeAssetID(gAgent.getSecureSessionID()); + + if (COMPLAINT_REPORT == mReportType) + { + mResourceDatap->mAssetInfo.mType = LLAssetType::AT_TEXTURE; + mResourceDatap->mPreferredLocation = LLFolderType::EType(LLResourceData::INVALID_LOCATION); + } + else + { + LL_WARNS() << "Unknown LLFloaterReporter type" << LL_ENDL; + } + mResourceDatap->mAssetInfo.mCreatorID = gAgentID; + mResourceDatap->mAssetInfo.setName("screenshot_name"); + mResourceDatap->mAssetInfo.setDescription("screenshot_descr"); + + // store in cache + LLFileSystem j2c_file(mResourceDatap->mAssetInfo.mUuid, mResourceDatap->mAssetInfo.mType, LLFileSystem::WRITE); + j2c_file.write(upload_data->getData(), upload_data->getDataSize()); + + // store in the image list so it doesn't try to fetch from the server + LLPointer<LLViewerFetchedTexture> image_in_list = + LLViewerTextureManager::getFetchedTexture(mResourceDatap->mAssetInfo.mUuid); + image_in_list->createGLTexture(0, mImageRaw, 0, true, LLGLTexture::OTHER); + + // the texture picker then uses that texture + LLTextureCtrl* texture = getChild<LLTextureCtrl>("screenshot"); + if (texture) + { + texture->setImageAssetID(mResourceDatap->mAssetInfo.mUuid); + texture->setDefaultImageAssetID(mResourceDatap->mAssetInfo.mUuid); + texture->setCaption(getString("Screenshot")); + } +} + +void LLFloaterReporter::takeNewSnapshot() +{ + childSetEnabled("send_btn", true); + mImageRaw = new LLImageRaw; + const S32 IMAGE_WIDTH = 1024; + const S32 IMAGE_HEIGHT = 768; + + // Take a screenshot, but don't draw this floater. + setVisible(false); + if (!gViewerWindow->rawSnapshot(mImageRaw,IMAGE_WIDTH, IMAGE_HEIGHT, true, false, true /*UI*/, true, false)) + { + LL_WARNS() << "Unable to take screenshot" << LL_ENDL; + setVisible(true); + return; + } + setVisible(true); + + if(gSavedPerAccountSettings.getBOOL("PreviousScreenshotForReport")) + { + std::string screenshot_filename(gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + SCREEN_PREV_FILENAME); + mPrevImageRaw = new LLImageRaw; + LLPointer<LLImagePNG> start_image_png = new LLImagePNG; + if(start_image_png->load(screenshot_filename)) + { + if (start_image_png->decode(mPrevImageRaw, 0.0f)) + { + LLNotificationsUtil::add("LoadPreviousReportScreenshot", LLSD(), LLSD(), boost::bind(&LLFloaterReporter::onLoadScreenshotDialog,this, _1, _2)); + return; + } + } + } + takeScreenshot(); +} + + +void LLFloaterReporter::onOpen(const LLSD& key) +{ + childSetEnabled("send_btn", false); + //Time delay to avoid UI artifacts. MAINT-7067 + mSnapshotTimer.start(); +} + +void LLFloaterReporter::onLoadScreenshotDialog(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + takeScreenshot(option == 0); +} + +void LLFloaterReporter::uploadImage() +{ + LL_INFOS() << "*** Uploading: " << LL_ENDL; + LL_INFOS() << "Type: " << LLAssetType::lookup(mResourceDatap->mAssetInfo.mType) << LL_ENDL; + LL_INFOS() << "UUID: " << mResourceDatap->mAssetInfo.mUuid << LL_ENDL; + LL_INFOS() << "Name: " << mResourceDatap->mAssetInfo.getName() << LL_ENDL; + LL_INFOS() << "Desc: " << mResourceDatap->mAssetInfo.getDescription() << LL_ENDL; + + gAssetStorage->storeAssetData(mResourceDatap->mAssetInfo.mTransactionID, + mResourceDatap->mAssetInfo.mType, + LLFloaterReporter::uploadDoneCallback, + (void*)mResourceDatap, true); +} + + +// static +void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data, S32 result, LLExtStat ext_status) // StoreAssetData callback (fixed) +{ + LLUploadDialog::modalUploadFinished(); + + LLResourceData* data = (LLResourceData*)user_data; + + if(result < 0) + { + LLSD args; + args["REASON"] = std::string(LLAssetStorage::getErrorString(result)); + LLNotificationsUtil::add("ErrorUploadingReportScreenshot", args); + + std::string err_msg("There was a problem uploading a report screenshot"); + err_msg += " due to the following reason: " + args["REASON"].asString(); + LL_WARNS() << err_msg << LL_ENDL; + return; + } + + if (data->mPreferredLocation != LLResourceData::INVALID_LOCATION) + { + LL_WARNS() << "Unknown report type : " << data->mPreferredLocation << LL_ENDL; + } + + LLFloaterReporter *self = LLFloaterReg::findTypedInstance<LLFloaterReporter>("reporter"); + if (self) + { + self->mScreenID = uuid; + LL_INFOS() << "Got screen shot " << uuid << LL_ENDL; + self->sendReportViaLegacy(self->gatherReport()); + LLNotificationsUtil::add("HelpReportAbuseConfirm"); + self->closeFloater(); + } +} + + +void LLFloaterReporter::setPosBox(const LLVector3d &pos) +{ + mPosition.setVec(pos); + std::string pos_string = llformat("{%.1f, %.1f, %.1f}", + mPosition.mV[VX], + mPosition.mV[VY], + mPosition.mV[VZ]); + getChild<LLUICtrl>("pos_field")->setValue(pos_string); +} + +void LLFloaterReporter::onClose(bool app_quitting) +{ + mSnapshotTimer.stop(); + gSavedPerAccountSettings.setBOOL("PreviousScreenshotForReport", app_quitting); +} |