llfloaterreporter.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include <sstream>
00035 
00036 // self include
00037 #include "llfloaterreporter.h"
00038 
00039 // linden library includes
00040 #include "llassetstorage.h"
00041 #include "llcachename.h"
00042 #include "llfontgl.h"
00043 #include "llgl.h"                       // for renderer
00044 #include "llinventory.h"
00045 #include "llstring.h"
00046 #include "llsys.h"
00047 #include "llversionviewer.h"
00048 #include "message.h"
00049 #include "v3math.h"
00050 
00051 // viewer project includes
00052 #include "llagent.h"
00053 #include "llbutton.h"
00054 #include "llcheckboxctrl.h"
00055 #include "llinventoryview.h"
00056 #include "lllineeditor.h"
00057 #include "lltexturectrl.h"
00058 #include "llscrolllistctrl.h"
00059 #include "llimview.h"
00060 #include "lltextbox.h"
00061 #include "lldispatcher.h"
00062 #include "llviewertexteditor.h"
00063 #include "llviewerobject.h"
00064 #include "llviewerregion.h"
00065 #include "llcombobox.h"
00066 #include "lltooldraganddrop.h"
00067 #include "llfloatermap.h"
00068 #include "lluiconstants.h"
00069 #include "lluploaddialog.h"
00070 #include "llcallingcard.h"
00071 #include "llviewerobjectlist.h"
00072 #include "lltoolobjpicker.h"
00073 #include "lltoolmgr.h"
00074 #include "llresourcedata.h"             // for LLResourceData
00075 #include "llviewerwindow.h"
00076 #include "llviewerimagelist.h"
00077 #include "llworldmap.h"
00078 #include "llfilepicker.h"
00079 #include "llfloateravatarpicker.h"
00080 #include "lldir.h"
00081 #include "llselectmgr.h"
00082 #include "llviewerbuild.h"
00083 #include "llvieweruictrlfactory.h"
00084 #include "viewer.h"
00085 
00086 #include "llassetuploadresponders.h"
00087 
00088 const U32 INCLUDE_SCREENSHOT  = 0x01 << 0;
00089 
00090 //-----------------------------------------------------------------------------
00091 // Globals
00092 //-----------------------------------------------------------------------------
00093 
00094 // this map keeps track of current reporter instances
00095 // there can only be one instance of each reporter type
00096 LLMap< EReportType, LLFloaterReporter* > gReporterInstances;
00097 
00098 // keeps track of where email is going to - global to avoid a pile
00099 // of static/non-static access outside my control
00100 namespace {
00101         static BOOL gEmailToEstateOwner = FALSE;
00102         static BOOL gDialogVisible = FALSE;
00103 }
00104 
00105 //-----------------------------------------------------------------------------
00106 // Member functions
00107 //-----------------------------------------------------------------------------
00108 LLFloaterReporter::LLFloaterReporter(
00109         const std::string& name,
00110         const LLRect& rect, 
00111         const std::string& title, 
00112         EReportType report_type)
00113         :       
00114         LLFloater(name, rect, title),
00115         mReportType(report_type),
00116         mObjectID(),
00117         mScreenID(),
00118         mAbuserID(),
00119         mDeselectOnClose( FALSE ),
00120         mPicking( FALSE), 
00121         mPosition(),
00122         mCopyrightWarningSeen( FALSE ),
00123         mResourceDatap(new LLResourceData())
00124 {
00125         if (report_type == BUG_REPORT)
00126         {
00127                 gUICtrlFactory->buildFloater(this, "floater_report_bug.xml");
00128         }
00129         else
00130         {
00131                 gUICtrlFactory->buildFloater(this, "floater_report_abuse.xml");
00132         }
00133 
00134         LLViewerRegion *regionp = gAgent.getRegion();
00135         if (regionp)
00136         {
00137                 childSetText("sim_field", regionp->getName() );
00138                 childSetText("abuse_location_edit", regionp->getName() );
00139         }
00140 
00141         LLButton* pick_btn = LLUICtrlFactory::getButtonByName(this, "pick_btn");
00142         if (pick_btn)
00143         {
00144                 // XUI: Why aren't these in viewerart.ini?
00145                 pick_btn->setImages( "UIImgFaceUUID",
00146                                                         "UIImgFaceSelectedUUID" );
00147                 childSetAction("pick_btn", onClickObjPicker, this);
00148         }
00149 
00150         if (report_type != BUG_REPORT)
00151         {
00152                 // abuser name is selected from a list
00153                 LLLineEditor* le = (LLLineEditor*)getCtrlByNameAndType("abuser_name_edit", WIDGET_TYPE_LINE_EDITOR);
00154                 le->setEnabled( FALSE );
00155         }
00156 
00157         childSetAction("select_abuser", onClickSelectAbuser, this);
00158 
00159         childSetAction("send_btn", onClickSend, this);
00160         childSetAction("cancel_btn", onClickCancel, this);
00161 
00162         enableControls(TRUE);
00163 
00164         // convert the position to a string
00165         LLVector3d pos = gAgent.getPositionGlobal();
00166         if (regionp)
00167         {
00168                 pos -= regionp->getOriginGlobal();
00169         }
00170         setPosBox(pos);
00171 
00172         gReporterInstances.addData(report_type, this);
00173 
00174         // Take a screenshot, but don't draw this floater.
00175         setVisible(FALSE);
00176         takeScreenshot();
00177         setVisible(TRUE);
00178 
00179         // Default text to be blank
00180         childSetText("object_name", LLString::null);
00181         childSetText("owner_name", LLString::null);
00182 
00183         childSetFocus("summary_edit");
00184 
00185         mDefaultSummary = childGetText("details_edit");
00186 
00187         gDialogVisible = TRUE;
00188 
00189         // only request details for abuse reports (not BUG reports)
00190         if (report_type != BUG_REPORT)
00191         {
00192                 // send a message and ask for information about this region - 
00193                 // result comes back in processRegionInfo(..)
00194                 LLMessageSystem* msg = gMessageSystem;
00195                 msg->newMessage("RequestRegionInfo");
00196                 msg->nextBlock("AgentData");
00197                 msg->addUUID("AgentID", gAgent.getID());
00198                 msg->addUUID("SessionID", gAgent.getSessionID());
00199                 gAgent.sendReliableMessage();
00200         };
00201 }
00202 
00203 // static
00204 void LLFloaterReporter::processRegionInfo(LLMessageSystem* msg)
00205 {
00206         U32 region_flags;
00207         msg->getU32("RegionInfo", "RegionFlags", region_flags);
00208         gEmailToEstateOwner = ( region_flags & REGION_FLAGS_ABUSE_EMAIL_TO_ESTATE_OWNER );
00209 
00210         if ( gDialogVisible )
00211         {
00212                 if ( gEmailToEstateOwner )
00213                 {
00214                         gViewerWindow->alertXml("HelpReportAbuseEmailEO");
00215                 }
00216                 else
00217                         gViewerWindow->alertXml("HelpReportAbuseEmailLL");
00218         };
00219 }
00220 
00221 // virtual
00222 LLFloaterReporter::~LLFloaterReporter()
00223 {
00224         gReporterInstances.removeData(mReportType);
00225         // child views automatically deleted
00226         mObjectID               = LLUUID::null;
00227 
00228         if (mPicking)
00229         {
00230                 closePickTool(this);
00231         }
00232 
00233         mPosition.setVec(0.0f, 0.0f, 0.0f);
00234 
00235         std::for_each(mMCDList.begin(), mMCDList.end(), DeletePointer() );
00236         mMCDList.clear();
00237 
00238         delete mResourceDatap;
00239         gDialogVisible = FALSE;
00240 }
00241 
00242 // virtual
00243 void LLFloaterReporter::draw()
00244 {
00245         // this is set by a static callback sometime after the dialog is created.
00246         // Only disable screenshot for abuse reports to estate owners - bug reports always
00247         // allow screenshots to be taken.
00248         if ( gEmailToEstateOwner && ( mReportType != BUG_REPORT ) )
00249         {
00250                 childSetValue("screen_check", FALSE );
00251                 childSetEnabled("screen_check", FALSE );
00252         }
00253         else
00254         {
00255                 childSetEnabled("screen_check", TRUE );
00256         }
00257 
00258         LLFloater::draw();
00259 }
00260 
00261 void LLFloaterReporter::enableControls(BOOL enable)
00262 {
00263         childSetEnabled("category_combo", enable);
00264         // bug reports never include the chat history
00265         if (mReportType != BUG_REPORT)
00266         {
00267                 childSetEnabled("chat_check", enable);
00268         }
00269         childSetEnabled("screen_check", enable);
00270         childDisable("screenshot");
00271         childSetEnabled("pick_btn",             enable);
00272         childSetEnabled("summary_edit", enable);
00273         childSetEnabled("details_edit", enable);
00274         childSetEnabled("send_btn",             enable);
00275         childSetEnabled("cancel_btn",   enable);
00276 }
00277 
00278 void LLFloaterReporter::getObjectInfo(const LLUUID& object_id)
00279 {
00280         // TODO -- 
00281         // 1 need to send to correct simulator if object is not 
00282         //   in same simulator as agent
00283         // 2 display info in widget window that gives feedback that
00284         //   we have recorded the object info
00285         // 3 can pick avatar ==> might want to indicate when a picked 
00286         //   object is an avatar, attachment, or other category
00287 
00288         mObjectID = object_id;
00289 
00290         if (LLUUID::null != mObjectID)
00291         {
00292                 // get object info for the user's benefit
00293                 LLViewerObject* objectp = NULL;
00294                 objectp = gObjectList.findObject( mObjectID );
00295                 if (objectp)
00296                 {
00297                         if ( objectp->isAttachment() )
00298                         {
00299                                 objectp = (LLViewerObject*)objectp->getRoot();
00300                         }
00301 
00302                         // correct the region and position information
00303                         LLViewerRegion *regionp = objectp->getRegion();
00304                         if (regionp)
00305                         {
00306                                 childSetText("sim_field", regionp->getName());
00307                                 LLVector3d global_pos;
00308                                 global_pos.setVec(objectp->getPositionRegion());
00309                                 setPosBox(global_pos);
00310                         }
00311         
00312                         if (objectp->isAvatar())
00313                         {
00314                                 // we have the information we need
00315                                 LLString object_owner;
00316 
00317                                 LLNameValue* firstname = objectp->getNVPair("FirstName");
00318                                 LLNameValue* lastname =  objectp->getNVPair("LastName");
00319                                 if (firstname && lastname)
00320                                 {
00321                                         object_owner.append(firstname->getString());
00322                                         object_owner.append(1, ' ');
00323                                         object_owner.append(lastname->getString());
00324                                 }
00325                                 else
00326                                 {
00327                                         object_owner.append("Unknown");
00328                                 }
00329                                 childSetText("object_name", object_owner);
00330                                 childSetText("owner_name", object_owner);
00331                                 childSetText("abuser_name_edit", object_owner);
00332                                 mAbuserID = object_id;
00333                         }
00334                         else
00335                         {
00336                                 // we have to query the simulator for information 
00337                                 // about this object
00338                                 LLMessageSystem* msg = gMessageSystem;
00339                                 U32 request_flags = (mReportType == BUG_REPORT) ? BUG_REPORT_REQUEST : COMPLAINT_REPORT_REQUEST;
00340                                 msg->newMessageFast(_PREHASH_RequestObjectPropertiesFamily);
00341                                 msg->nextBlockFast(_PREHASH_AgentData);
00342                                 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00343                                 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00344                                 msg->nextBlockFast(_PREHASH_ObjectData);
00345                                 msg->addU32Fast(_PREHASH_RequestFlags, request_flags );
00346                                 msg->addUUIDFast(_PREHASH_ObjectID,     mObjectID);
00347                                 LLViewerRegion* regionp = objectp->getRegion();
00348                                 msg->sendReliable( regionp->getHost() );
00349                         }
00350                 }
00351         }
00352 }
00353 
00354 
00355 // static
00356 void LLFloaterReporter::onClickSelectAbuser(void *userdata)
00357 {
00358         LLFloaterReporter *self = (LLFloaterReporter *)userdata;
00359 
00360         gFloaterView->getParentFloater(self)->addDependentFloater(LLFloaterAvatarPicker::show(callbackAvatarID, userdata, FALSE, TRUE ));
00361 }
00362 
00363 // static
00364 void LLFloaterReporter::callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data)
00365 {
00366         LLFloaterReporter* self = (LLFloaterReporter*) data;
00367 
00368         if (ids.empty() || names.empty()) return;
00369 
00370         // this should never be called in a bug report but here for safety.
00371         if ( self->mReportType != BUG_REPORT )
00372         {
00373                 self->childSetText("abuser_name_edit", names[0] );
00374                 
00375                 self->mAbuserID = ids[0];
00376 
00377                 self->refresh();
00378         };
00379 }
00380 
00381 // static
00382 void LLFloaterReporter::onClickSend(void *userdata)
00383 {
00384         LLFloaterReporter *self = (LLFloaterReporter *)userdata;
00385         
00386         if (self->mPicking)
00387         {
00388                 closePickTool(self);
00389         }
00390 
00391         if(self->validateReport())
00392         {
00393                 // only show copyright alert for abuse reports
00394                 if ( self->mReportType != BUG_REPORT )
00395                 {
00396                         if ( ! self->mCopyrightWarningSeen )
00397                         {
00398                                 LLString details_lc = self->childGetText("details_edit");
00399                                 LLString::toLower( details_lc );
00400                                 LLString summary_lc = self->childGetText("summary_edit");
00401                                 LLString::toLower( summary_lc );
00402                                 if ( details_lc.find( "copyright" ) != std::string::npos ||
00403                                         summary_lc.find( "copyright" ) != std::string::npos )
00404                                 {
00405                                         gViewerWindow->alertXml("HelpReportAbuseContainsCopyright");
00406                                         self->mCopyrightWarningSeen = TRUE;
00407                                         return;
00408                                 };
00409                         };
00410                 };
00411 
00412                 LLUploadDialog::modalUploadDialog("Uploading...\n\nReport");
00413                 // *TODO don't upload image if checkbox isn't checked
00414                 std::string url = gAgent.getRegion()->getCapability("SendUserReport");
00415                 std::string sshot_url = gAgent.getRegion()->getCapability("SendUserReportWithScreenshot");
00416                 if(!url.empty() || !sshot_url.empty())
00417                 {
00418                         self->sendReportViaCaps(url, sshot_url, self->gatherReport());
00419                         self->close();
00420                 }
00421                 else
00422                 {
00423                         if(self->childGetValue("screen_check"))
00424                         {
00425                                 self->childDisable("send_btn");
00426                                 self->childDisable("cancel_btn");
00427                                 // the callback from uploading the image calls sendReportViaLegacy()
00428                                 self->uploadImage();
00429                         }
00430                         else
00431                         {
00432                                 self->sendReportViaLegacy(self->gatherReport());
00433                                 LLUploadDialog::modalUploadFinished();
00434                                 self->close();
00435                         }
00436                 }
00437         }
00438 }
00439 
00440 
00441 // static
00442 void LLFloaterReporter::onClickCancel(void *userdata)
00443 {
00444         LLFloaterReporter *self = (LLFloaterReporter *)userdata;
00445 
00446         // reset flag in case the next report also contains this text
00447         self->mCopyrightWarningSeen = FALSE;
00448 
00449         if (self->mPicking)
00450         {
00451                 closePickTool(self);
00452         }
00453         self->close();
00454 }
00455 
00456 
00457 // static 
00458 void LLFloaterReporter::onClickObjPicker(void *userdata)
00459 {
00460         LLFloaterReporter *self = (LLFloaterReporter *)userdata;
00461         gToolObjPicker->setExitCallback(LLFloaterReporter::closePickTool, self);
00462         gToolMgr->setTransientTool(gToolObjPicker);
00463         self->mPicking = TRUE;
00464         self->childSetText("object_name", LLString::null);
00465         self->childSetText("owner_name", LLString::null);
00466         LLButton* pick_btn = LLUICtrlFactory::getButtonByName(self, "pick_btn");
00467         if (pick_btn) pick_btn->setToggleState(TRUE);
00468 }
00469 
00470 
00471 // static
00472 void LLFloaterReporter::closePickTool(void *userdata)
00473 {
00474         LLFloaterReporter *self = (LLFloaterReporter *)userdata;
00475 
00476         LLUUID object_id = gToolObjPicker->getObjectID();
00477         self->getObjectInfo(object_id);
00478 
00479         gToolMgr->clearTransientTool();
00480         self->mPicking = FALSE;
00481         LLButton* pick_btn = LLUICtrlFactory::getButtonByName(self, "pick_btn");
00482         if (pick_btn) pick_btn->setToggleState(FALSE);
00483 }
00484 
00485 
00486 // static
00487 void LLFloaterReporter::showFromMenu(EReportType report_type)
00488 {
00489         if (gReporterInstances.checkData(report_type))
00490         {
00491                 // ...bring that window to front
00492                 LLFloaterReporter *f = gReporterInstances.getData(report_type);
00493                 f->open();              /* Flawfinder: ignore */
00494         }
00495         else
00496         {
00497                 LLFloaterReporter *f;
00498                 if (BUG_REPORT == report_type)
00499                 {
00500                         f = LLFloaterReporter::createNewBugReporter();
00501                 }
00502                 else if (COMPLAINT_REPORT == report_type)
00503                 {
00504                         f = LLFloaterReporter::createNewAbuseReporter();
00505                 }
00506                 else
00507                 {
00508                         llwarns << "Unknown LLViewerReporter type : " << report_type << llendl;
00509                         return;
00510                 }
00511 
00512                 f->center();
00513 
00514                 if (report_type == BUG_REPORT)
00515                 {
00516                         gViewerWindow->alertXml("HelpReportBug");
00517                 }
00518                 else
00519                 {
00520                         // popup for abuse reports is triggered elsewhere
00521                 }
00522 
00523                 // grab the user's name
00524                 LLString fullname;
00525                 gAgent.buildFullname(fullname);
00526                 f->childSetText("reporter_field", fullname);
00527         }
00528 }
00529 
00530 
00531 // static
00532 LLFloaterReporter* LLFloaterReporter::showFromObject(const LLUUID& object_id, bool show)
00533 {
00534         LLFloaterReporter* f = createNewAbuseReporter();
00535         f->center();
00536         f->setFocus(TRUE);
00537 
00538         // grab the user's name
00539         LLString fullname;
00540         gAgent.buildFullname(fullname);
00541         f->childSetText("reporter_field", fullname);
00542 
00543         // Request info for this object
00544         f->getObjectInfo(object_id);
00545 
00546         // Need to deselect on close
00547         f->mDeselectOnClose = TRUE;
00548 
00549         if ( show )
00550         {
00551                 f->open();              /* Flawfinder: ignore */
00552         }
00553         else
00554         {
00555                 gDialogVisible = FALSE;
00556         }
00557 
00558         return f;
00559 }
00560 
00561 
00562 // static 
00563 LLFloaterReporter* LLFloaterReporter::getReporter(EReportType report_type)
00564 {
00565         LLFloaterReporter *self = NULL;
00566         if (gReporterInstances.checkData(report_type))
00567         {
00568                 // ...bring that window to front
00569                 self = gReporterInstances.getData(report_type);
00570         }
00571         return self;
00572 }
00573 
00574 LLFloaterReporter* LLFloaterReporter::createNewAbuseReporter()
00575 {
00576         return new LLFloaterReporter("complaint_reporter",
00577                                                          LLRect(),
00578                                                                  "Report Abuse",
00579                                                                  COMPLAINT_REPORT);
00580 }
00581 
00582 //static
00583 LLFloaterReporter* LLFloaterReporter::createNewBugReporter()
00584 {
00585         return new LLFloaterReporter("bug_reporter",
00586                                                  LLRect(),
00587                                                      "Report Bug",
00588                                          BUG_REPORT);
00589 }
00590         
00591 
00592 
00593 void LLFloaterReporter::setPickedObjectProperties(const LLString& object_name, const LLString& owner_name, const LLUUID owner_id)
00594 {
00595         childSetText("object_name", object_name);
00596         childSetText("owner_name", owner_name);
00597         childSetText("abuser_name_edit", owner_name);
00598         mAbuserID = owner_id;
00599 }
00600 
00601 
00602 bool LLFloaterReporter::validateReport()
00603 {
00604         // Ensure user selected a category from the list
00605         LLSD category_sd = childGetValue("category_combo");
00606         U8 category = (U8)category_sd.asInteger();
00607         if (category == 0)
00608         {
00609                 if ( mReportType != BUG_REPORT )
00610                 {
00611                         gViewerWindow->alertXml("HelpReportAbuseSelectCategory");
00612                 }
00613                 else
00614                 {
00615                         gViewerWindow->alertXml("HelpReportBugSelectCategory");
00616                 }
00617                 return false;
00618         }
00619 
00620         if ( mReportType != BUG_REPORT )
00621         {
00622           if ( childGetText("abuser_name_edit").empty() )
00623           {
00624                   gViewerWindow->alertXml("HelpReportAbuseAbuserNameEmpty");
00625                   return false;
00626           };
00627   
00628           if ( childGetText("abuse_location_edit").empty() )
00629           {
00630                   gViewerWindow->alertXml("HelpReportAbuseAbuserLocationEmpty");
00631                   return false;
00632           };
00633         };
00634 
00635         if ( childGetText("summary_edit").empty() )
00636         {
00637                 if ( mReportType != BUG_REPORT )
00638                 {
00639                         gViewerWindow->alertXml("HelpReportAbuseSummaryEmpty");
00640                 }
00641                 else
00642                 {
00643                         gViewerWindow->alertXml("HelpReportBugSummaryEmpty");
00644                 }
00645                 return false;
00646         };
00647 
00648         if ( childGetText("details_edit") == mDefaultSummary )
00649         {
00650                 if ( mReportType != BUG_REPORT )
00651                 {
00652                         gViewerWindow->alertXml("HelpReportAbuseDetailsEmpty");
00653                 }
00654                 else
00655                 {
00656                         gViewerWindow->alertXml("HelpReportBugDetailsEmpty");
00657                 }
00658                 return false;
00659         };
00660         return true;
00661 }
00662 
00663 LLSD LLFloaterReporter::gatherReport()
00664 {       
00665         LLViewerRegion *regionp = gAgent.getRegion();
00666         if (!regionp) return LLSD(); // *TODO handle this failure case more gracefully
00667 
00668         // reset flag in case the next report also contains this text
00669         mCopyrightWarningSeen = FALSE;
00670 
00671         std::ostringstream summary;
00672         if (!gInProductionGrid)
00673         {
00674                 summary << "Preview ";
00675         }
00676 
00677         LLString category_name;
00678         LLComboBox* combo = LLUICtrlFactory::getComboBoxByName(this, "category_combo");
00679         if (combo)
00680         {
00681                 category_name = combo->getSimpleSelectedItem(); // want label, not value
00682         }
00683 
00684 #if LL_WINDOWS
00685         const char* platform = "Win";
00686         const char* short_platform = "O:W";
00687 #elif LL_DARWIN
00688         const char* platform = "Mac";
00689         const char* short_platform = "O:M";
00690 #elif LL_LINUX
00691         const char* platform = "Lnx";
00692         const char* short_platform = "O:L";
00693 #else
00694         const char* platform = "???";
00695         const char* short_platform = "O:?";
00696 #endif
00697 
00698 
00699         if ( mReportType == BUG_REPORT)
00700         {
00701                 summary << short_platform << " V" << LL_VERSION_MAJOR << "."
00702                         << LL_VERSION_MINOR << "."
00703                         << LL_VERSION_PATCH << "."
00704                         << LL_VIEWER_BUILD << "."
00705                         << LL_VERSION_REVISION
00706                         << " (" << regionp->getName() << ")"
00707                         << "[" << category_name << "] "
00708                         << "\"" << childGetValue("summary_edit").asString() << "\"";
00709         }
00710         else
00711         {
00712                 summary << ""
00713                         << " |" << regionp->getName() << "|"                                                            // region reporter is currently in.
00714                         << " (" << childGetText("abuse_location_edit") << ")"                           // region abuse occured in (freeform text - no LLRegionPicker tool)
00715                         << " [" << category_name << "] "                                                                        // updated category
00716                         << " {" << childGetText("abuser_name_edit") << "} "                                     // name of abuse entered in report (chosen using LLAvatarPicker)
00717                         << " \"" << childGetValue("summary_edit").asString() << "\"";           // summary as entered
00718         };
00719 
00720         std::ostringstream details;
00721         if (mReportType != BUG_REPORT)
00722         {
00723                 details << "V" << LL_VERSION_MAJOR << "."                                                               // client version moved to body of email for abuse reports
00724                         << LL_VERSION_MINOR << "."
00725                         << LL_VERSION_PATCH << "."
00726                         << LL_VIEWER_BUILD << std::endl << std::endl;
00727         }
00728         LLString object_name = childGetText("object_name");
00729         LLString owner_name = childGetText("owner_name");
00730         if (!object_name.empty() && !owner_name.empty())
00731         {
00732                 details << "Object: " << object_name << "\n";
00733                 details << "Owner: " << owner_name << "\n";
00734         }
00735 
00736         if ( mReportType != BUG_REPORT )
00737         {
00738                 details << "Abuser name: " << childGetText("abuser_name_edit") << " \n";
00739                 details << "Abuser location: " << childGetText("abuse_location_edit") << " \n";
00740         };
00741 
00742         details << childGetValue("details_edit").asString();
00743 
00744         char version_string[MAX_STRING];                /* Flawfinder: ignore */
00745         snprintf(version_string,                                /* Flawfinder: ignore */
00746                         MAX_STRING,
00747                         "%d.%d.%d %s %s %s %s",
00748                         LL_VERSION_MAJOR,
00749                         LL_VERSION_MINOR,
00750                         LL_VERSION_PATCH,
00751                         platform,
00752                         gSysCPU.getFamily().c_str(),
00753                         gGLManager.mGLRenderer.c_str(),
00754                         gGLManager.mDriverVersionVendorString.c_str());
00755 
00756         // only send a screenshot ID if we're asked to and the email is 
00757         // going to LL - Estate Owners cannot see the screenshot asset
00758         LLUUID screenshot_id = LLUUID::null;
00759         if (childGetValue("screen_check"))
00760         {
00761                 if ( mReportType != BUG_REPORT )
00762                 {
00763                         if ( gEmailToEstateOwner == FALSE )
00764                         {
00765                                 screenshot_id = childGetValue("screenshot");
00766                         }
00767                 }
00768                 else
00769                 {
00770                         screenshot_id = childGetValue("screenshot");
00771                 };
00772         };
00773 
00774         LLSD report = LLSD::emptyMap();
00775         report["report-type"] = (U8) mReportType;
00776         report["category"] = childGetValue("category_combo");
00777         report["position"] = mPosition.getValue();
00778         report["check-flags"] = (U8)0; // this is not used
00779         report["screenshot-id"] = screenshot_id;
00780         report["object-id"] = mObjectID;
00781         report["abuser-id"] = mAbuserID;
00782         report["abuse-region-name"] = "";
00783         report["abuse-region-id"] = LLUUID::null;
00784         report["summary"] = summary.str();
00785         report["version-string"] = version_string;
00786         report["details"] = details.str();
00787         return report;
00788 }
00789 
00790 void LLFloaterReporter::sendReportViaLegacy(const LLSD & report)
00791 {
00792         LLViewerRegion *regionp = gAgent.getRegion();
00793         if (!regionp) return;
00794         LLMessageSystem *msg = gMessageSystem;
00795         msg->newMessageFast(_PREHASH_UserReport);
00796         msg->nextBlockFast(_PREHASH_AgentData);
00797         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00798         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00799         
00800         msg->nextBlockFast(_PREHASH_ReportData);
00801         msg->addU8Fast(_PREHASH_ReportType, report["report-type"].asInteger());
00802         msg->addU8(_PREHASH_Category, report["category"].asInteger());
00803         msg->addVector3Fast(_PREHASH_Position,  LLVector3(report["position"]));
00804         msg->addU8Fast(_PREHASH_CheckFlags, report["check-flags"].asInteger());
00805         msg->addUUIDFast(_PREHASH_ScreenshotID, report["screenshot-id"].asUUID());
00806         msg->addUUIDFast(_PREHASH_ObjectID, report["object-id"].asUUID());
00807         msg->addUUID("AbuserID", report["abuser-id"].asUUID());
00808         msg->addString("AbuseRegionName", report["abuse-region-name"].asString());
00809         msg->addUUID("AbuseRegionID", report["abuse-region-id"].asUUID());
00810 
00811         msg->addStringFast(_PREHASH_Summary, report["summary"].asString().c_str());
00812         msg->addString("VersionString", report["version-string"]);
00813         msg->addStringFast(_PREHASH_Details, report["details"] );
00814         
00815         msg->sendReliable(regionp->getHost());
00816 }
00817 
00818 class LLUserReportScreenshotResponder : public LLAssetUploadResponder
00819 {
00820 public:
00821         LLUserReportScreenshotResponder(const LLSD & post_data, 
00822                                                                         const LLUUID & vfile_id, 
00823                                                                         LLAssetType::EType asset_type):
00824           LLAssetUploadResponder(post_data, vfile_id, asset_type)
00825         {
00826         }
00827         void uploadFailed(const LLSD& content)
00828         {
00829                 // *TODO pop up a dialog so the user knows their report screenshot didn't make it
00830                 LLUploadDialog::modalUploadFinished();
00831         }
00832         void uploadComplete(const LLSD& content)
00833         {
00834                 // we don't care about what the server returns from this post, just clean up the UI
00835                 LLUploadDialog::modalUploadFinished();
00836         }
00837 };
00838 
00839 class LLUserReportResponder : public LLHTTPClient::Responder
00840 {
00841 public:
00842         LLUserReportResponder(): LLHTTPClient::Responder()  {}
00843 
00844         void error(U32 status, const std::string& reason)
00845         {
00846                 // *TODO do some user messaging here
00847                 LLUploadDialog::modalUploadFinished();
00848         }
00849         void result(const LLSD& content)
00850         {
00851                 // we don't care about what the server returns
00852                 LLUploadDialog::modalUploadFinished();
00853         }
00854 };
00855 
00856 void LLFloaterReporter::sendReportViaCaps(std::string url, std::string sshot_url, const LLSD& report)
00857 {
00858         if(childGetValue("screen_check").asBoolean() && !sshot_url.empty())
00859         {
00860                 // try to upload screenshot
00861                 LLHTTPClient::post(sshot_url, report, new LLUserReportScreenshotResponder(report, 
00862                                                                                                                         mResourceDatap->mAssetInfo.mUuid, 
00863                                                                                                                         mResourceDatap->mAssetInfo.mType));                     
00864         }
00865         else
00866         {
00867                 // screenshot not wanted or we don't have screenshot cap
00868                 LLHTTPClient::post(url, report, new LLUserReportResponder());                   
00869         }
00870 }
00871 
00872 void LLFloaterReporter::takeScreenshot()
00873 {
00874         const S32 IMAGE_WIDTH = 1024;
00875         const S32 IMAGE_HEIGHT = 768;
00876 
00877         LLPointer<LLImageRaw> raw = new LLImageRaw;
00878         if( !gViewerWindow->rawSnapshot(raw, IMAGE_WIDTH, IMAGE_HEIGHT, TRUE, TRUE, FALSE))
00879         {
00880                 llwarns << "Unable to take screenshot" << llendl;
00881                 return;
00882         }
00883         LLPointer<LLImageJ2C> upload_data = LLViewerImageList::convertToUploadFile(raw);
00884 
00885         // create a resource data
00886         mResourceDatap->mInventoryType = LLInventoryType::IT_NONE;
00887         mResourceDatap->mAssetInfo.mTransactionID.generate();
00888         mResourceDatap->mAssetInfo.mUuid = mResourceDatap->mAssetInfo.mTransactionID.makeAssetID(gAgent.getSecureSessionID());
00889         if (BUG_REPORT == mReportType)
00890         {
00891                 mResourceDatap->mAssetInfo.mType = LLAssetType::AT_TEXTURE;
00892                 mResourceDatap->mPreferredLocation = LLAssetType::EType(-1);
00893         }
00894         else if (COMPLAINT_REPORT == mReportType)
00895         {
00896                 mResourceDatap->mAssetInfo.mType = LLAssetType::AT_TEXTURE;
00897                 mResourceDatap->mPreferredLocation = LLAssetType::EType(-2);
00898         }
00899         else
00900         {
00901                 llwarns << "Unknown LLFloaterReporter type" << llendl;
00902         }
00903         mResourceDatap->mAssetInfo.mCreatorID = gAgentID;
00904         mResourceDatap->mAssetInfo.setName("screenshot_name");
00905         mResourceDatap->mAssetInfo.setDescription("screenshot_descr");
00906 
00907         // store in VFS
00908         LLVFile::writeFile(upload_data->getData(), 
00909                                                 upload_data->getDataSize(), 
00910                                                 gVFS, 
00911                                                 mResourceDatap->mAssetInfo.mUuid, 
00912                                                 mResourceDatap->mAssetInfo.mType);
00913 
00914         // store in the image list so it doesn't try to fetch from the server
00915         LLViewerImage* image_in_list = new LLViewerImage(mResourceDatap->mAssetInfo.mUuid, TRUE);
00916         image_in_list->createGLTexture(0, raw);
00917         gImageList.addImage(image_in_list); 
00918 
00919         // the texture picker then uses that texture
00920         LLTexturePicker* texture = LLUICtrlFactory::getTexturePickerByName(this, "screenshot");
00921         if (texture)
00922         {
00923                 texture->setImageAssetID(mResourceDatap->mAssetInfo.mUuid);
00924                 texture->setDefaultImageAssetID(mResourceDatap->mAssetInfo.mUuid);
00925                 texture->setCaption("Screenshot");
00926         }
00927 
00928 }
00929 
00930 void LLFloaterReporter::uploadImage()
00931 {
00932         llinfos << "*** Uploading: " << llendl;
00933         llinfos << "Type: " << LLAssetType::lookup(mResourceDatap->mAssetInfo.mType) << llendl;
00934         llinfos << "UUID: " << mResourceDatap->mAssetInfo.mUuid << llendl;
00935         llinfos << "Name: " << mResourceDatap->mAssetInfo.getName() << llendl;
00936         llinfos << "Desc: " << mResourceDatap->mAssetInfo.getDescription() << llendl;
00937 
00938         gAssetStorage->storeAssetData(mResourceDatap->mAssetInfo.mTransactionID,
00939                                                                         mResourceDatap->mAssetInfo.mType,
00940                                                                         LLFloaterReporter::uploadDoneCallback,
00941                                                                         (void*)mResourceDatap, TRUE);
00942 }
00943 
00944 
00945 // static
00946 void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data, S32 result, LLExtStat ext_status) // StoreAssetData callback (fixed)
00947 {
00948         LLUploadDialog::modalUploadFinished();
00949 
00950         LLResourceData* data = (LLResourceData*)user_data;
00951 
00952         if(result < 0)
00953         {
00954                 LLStringBase<char>::format_map_t args;
00955                 args["[REASON]"] = std::string(LLAssetStorage::getErrorString(result));
00956                 gViewerWindow->alertXml("ErrorUploadingReportScreenshot", args);
00957 
00958                 std::string err_msg("There was a problem uploading a report screenshot");
00959                 err_msg += " due to the following reason: " + args["[REASON]"];
00960                 llwarns << err_msg << llendl;
00961                 return;
00962         }
00963 
00964         EReportType report_type = UNKNOWN_REPORT;
00965         if (data->mPreferredLocation == -1)
00966         {
00967                 report_type = BUG_REPORT;
00968         }
00969         else if (data->mPreferredLocation == -2)
00970         {
00971                 report_type = COMPLAINT_REPORT;
00972         }
00973         else 
00974         {
00975                 llwarns << "Unknown report type : " << data->mPreferredLocation << llendl;
00976         }
00977 
00978         LLFloaterReporter *self = getReporter(report_type);
00979         if (self)
00980         {
00981                 self->mScreenID = uuid;
00982                 llinfos << "Got screen shot " << uuid << llendl;
00983                 self->sendReportViaLegacy(self->gatherReport());
00984                 self->close();
00985         }
00986 }
00987 
00988 
00989 void LLFloaterReporter::setPosBox(const LLVector3d &pos)
00990 {
00991         mPosition.setVec(pos);
00992         LLString pos_string = llformat("{%.1f, %.1f, %.1f}",
00993                 mPosition.mV[VX],
00994                 mPosition.mV[VY],
00995                 mPosition.mV[VZ]);
00996         childSetText("pos_field", pos_string);
00997 }
00998 
00999 void LLFloaterReporter::setDescription(const LLString& description, LLMeanCollisionData *mcd)
01000 {
01001         LLFloaterReporter *self = gReporterInstances[COMPLAINT_REPORT];
01002         if (self)
01003         {
01004                 self->childSetText("details_edit", description);
01005 
01006                 for_each(self->mMCDList.begin(), self->mMCDList.end(), DeletePointer());
01007                 self->mMCDList.clear();
01008                 if (mcd)
01009                 {
01010                         self->mMCDList.push_back(new LLMeanCollisionData(mcd));
01011                 }
01012         }
01013 }
01014 
01015 void LLFloaterReporter::addDescription(const LLString& description, LLMeanCollisionData *mcd)
01016 {
01017         LLFloaterReporter *self = gReporterInstances[COMPLAINT_REPORT];
01018         if (self)
01019         {
01020                 LLTextEditor* text = LLUICtrlFactory::getTextEditorByName(self, "details_edit");
01021                 if (text)
01022                 {       
01023                         text->insertText(description);
01024                 }
01025                 if (mcd)
01026                 {
01027                         self->mMCDList.push_back(new LLMeanCollisionData(mcd));
01028                 }
01029         }
01030 }

Generated on Thu Jul 1 06:08:36 2010 for Second Life Viewer by  doxygen 1.4.7