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

Generated on Fri May 16 08:33:30 2008 for SecondLife by  doxygen 1.5.5