diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/newview/llviewermessage.cpp | 520 |
1 files changed, 322 insertions, 198 deletions
diff --git a/linden/indra/newview/llviewermessage.cpp b/linden/indra/newview/llviewermessage.cpp index 5dab363..5eafd9d 100644 --- a/linden/indra/newview/llviewermessage.cpp +++ b/linden/indra/newview/llviewermessage.cpp | |||
@@ -145,8 +145,14 @@ extern BOOL gDebugClicks; | |||
145 | extern void bad_network_handler(); | 145 | extern void bad_network_handler(); |
146 | 146 | ||
147 | // function prototypes | 147 | // function prototypes |
148 | void open_offer(const std::vector<LLUUID>& items); | 148 | void open_offer(const std::vector<LLUUID>& items, const std::string& from_name); |
149 | void friendship_offer_callback(S32 option, void* user_data); | 149 | void friendship_offer_callback(S32 option, void* user_data); |
150 | bool check_offer_throttle(const std::string& from_name, bool check_only); | ||
151 | |||
152 | //inventory offer throttle globals | ||
153 | LLFrameTimer gThrottleTimer; | ||
154 | const U32 OFFER_THROTTLE_MAX_COUNT=5; //number of items per time period | ||
155 | const F32 OFFER_THROTTLE_TIME=10.f; //time period in seconds | ||
150 | 156 | ||
151 | struct LLFriendshipOffer | 157 | struct LLFriendshipOffer |
152 | { | 158 | { |
@@ -195,11 +201,6 @@ void give_money(const LLUUID& uuid, LLViewerRegion* region, S32 amount, BOOL is_ | |||
195 | } | 201 | } |
196 | } | 202 | } |
197 | 203 | ||
198 | BOOL can_afford_transaction(S32 cost) | ||
199 | { | ||
200 | return((cost <= 0)||((gStatusBar) && (gStatusBar->getBalance() >=cost))); | ||
201 | } | ||
202 | |||
203 | void send_complete_agent_movement(const LLHost& sim_host) | 204 | void send_complete_agent_movement(const LLHost& sim_host) |
204 | { | 205 | { |
205 | LLMessageSystem* msg = gMessageSystem; | 206 | LLMessageSystem* msg = gMessageSystem; |
@@ -275,11 +276,19 @@ void process_layer_data(LLMessageSystem *mesgsys, void **user_data) | |||
275 | 276 | ||
276 | mesgsys->getS8Fast(_PREHASH_LayerID, _PREHASH_Type, type); | 277 | mesgsys->getS8Fast(_PREHASH_LayerID, _PREHASH_Type, type); |
277 | size = mesgsys->getSizeFast(_PREHASH_LayerData, _PREHASH_Data); | 278 | size = mesgsys->getSizeFast(_PREHASH_LayerData, _PREHASH_Data); |
278 | if(!size) | 279 | if (0 == size) |
279 | { | 280 | { |
280 | llwarns << "Layer data has zero size." << llendl; | 281 | llwarns << "Layer data has zero size." << llendl; |
281 | return; | 282 | return; |
282 | } | 283 | } |
284 | if (size < 0) | ||
285 | { | ||
286 | // getSizeFast() is probably trying to tell us about an error | ||
287 | llwarns << "getSizeFast() returned negative result: " | ||
288 | << size | ||
289 | << llendl; | ||
290 | return; | ||
291 | } | ||
283 | U8 *datap = new U8[size]; | 292 | U8 *datap = new U8[size]; |
284 | mesgsys->getBinaryDataFast(_PREHASH_LayerData, _PREHASH_Data, datap, size); | 293 | mesgsys->getBinaryDataFast(_PREHASH_LayerData, _PREHASH_Data, datap, size); |
285 | LLVLData *vl_datap = new LLVLData(regionp, type, datap, size); | 294 | LLVLData *vl_datap = new LLVLData(regionp, type, datap, size); |
@@ -326,25 +335,29 @@ void export_complete() | |||
326 | while ((pos = strstr(pos+1, "<sl:image ")) != 0) | 335 | while ((pos = strstr(pos+1, "<sl:image ")) != 0) |
327 | { | 336 | { |
328 | char *pos_check = strstr(pos, "checksum=\""); | 337 | char *pos_check = strstr(pos, "checksum=\""); |
329 | char *pos_uuid = strstr(pos_check, "\">"); | ||
330 | 338 | ||
331 | if (pos_check && pos_uuid) | 339 | if (pos_check) |
332 | { | 340 | { |
333 | char image_uuid_str[UUID_STR_SIZE]; /* Flawfinder: ignore */ | 341 | char *pos_uuid = strstr(pos_check, "\">"); |
334 | memcpy(image_uuid_str, pos_uuid+2, UUID_STR_SIZE-1); /* Flawfinder: ignore */ | ||
335 | image_uuid_str[UUID_STR_SIZE-1] = 0; | ||
336 | 342 | ||
337 | LLUUID image_uuid(image_uuid_str); | 343 | if (pos_uuid) |
344 | { | ||
345 | char image_uuid_str[UUID_STR_SIZE]; /* Flawfinder: ignore */ | ||
346 | memcpy(image_uuid_str, pos_uuid+2, UUID_STR_SIZE-1); /* Flawfinder: ignore */ | ||
347 | image_uuid_str[UUID_STR_SIZE-1] = 0; | ||
348 | |||
349 | LLUUID image_uuid(image_uuid_str); | ||
338 | 350 | ||
339 | llinfos << "Found UUID: " << image_uuid << llendl; | 351 | llinfos << "Found UUID: " << image_uuid << llendl; |
340 | 352 | ||
341 | std::map<LLUUID, LLString>::iterator itor = gImageChecksums.find(image_uuid); | 353 | std::map<LLUUID, LLString>::iterator itor = gImageChecksums.find(image_uuid); |
342 | if (itor != gImageChecksums.end()) | 354 | if (itor != gImageChecksums.end()) |
343 | { | ||
344 | llinfos << "Replacing with checksum: " << itor->second << llendl; | ||
345 | if (itor->second.c_str() != NULL) | ||
346 | { | 355 | { |
347 | memcpy(&pos_check[10], itor->second.c_str(), 32); /* Flawfinder: ignore */ | 356 | llinfos << "Replacing with checksum: " << itor->second << llendl; |
357 | if (itor->second.c_str() != NULL) | ||
358 | { | ||
359 | memcpy(&pos_check[10], itor->second.c_str(), 32); /* Flawfinder: ignore */ | ||
360 | } | ||
348 | } | 361 | } |
349 | } | 362 | } |
350 | } | 363 | } |
@@ -354,7 +367,7 @@ void export_complete() | |||
354 | fwrite(buffer, 1, length, fXMLOut); | 367 | fwrite(buffer, 1, length, fXMLOut); |
355 | fclose(fXMLOut); | 368 | fclose(fXMLOut); |
356 | 369 | ||
357 | delete buffer; | 370 | delete [] buffer; |
358 | } | 371 | } |
359 | 372 | ||
360 | 373 | ||
@@ -432,7 +445,7 @@ void exported_j2c_complete(const LLTSCode status, void *user_data) | |||
432 | char *end = strrchr(file_path, gDirUtilp->getDirDelimiter()[0]); | 445 | char *end = strrchr(file_path, gDirUtilp->getDirDelimiter()[0]); |
433 | end[0] = 0; | 446 | end[0] = 0; |
434 | LLString output_file = llformat("%s/image-%03d.tga", file_path, image_num);//filename; | 447 | LLString output_file = llformat("%s/image-%03d.tga", file_path, image_num);//filename; |
435 | delete file_path; | 448 | delete [] file_path; |
436 | //S32 name_len = output_file.length(); | 449 | //S32 name_len = output_file.length(); |
437 | //strcpy(&output_file[name_len-3], "tga"); | 450 | //strcpy(&output_file[name_len-3], "tga"); |
438 | FILE* fOut = LLFile::fopen(output_file.c_str(), "wb"); /* Flawfinder: ignore */ | 451 | FILE* fOut = LLFile::fopen(output_file.c_str(), "wb"); /* Flawfinder: ignore */ |
@@ -599,31 +612,44 @@ void join_group_callback(S32 option, void* user_data) | |||
599 | class LLOpenAgentOffer : public LLInventoryFetchObserver | 612 | class LLOpenAgentOffer : public LLInventoryFetchObserver |
600 | { | 613 | { |
601 | public: | 614 | public: |
602 | LLOpenAgentOffer() {} | 615 | LLOpenAgentOffer(const std::string& from_name) : mFromName(from_name) {} |
603 | virtual ~LLOpenAgentOffer() {} | 616 | /*virtual*/ void done() |
604 | |||
605 | virtual void done() | ||
606 | { | 617 | { |
607 | open_offer(mComplete); | 618 | open_offer(mComplete, mFromName); |
608 | gInventory.removeObserver(this); | 619 | gInventory.removeObserver(this); |
609 | delete this; | 620 | delete this; |
610 | } | 621 | } |
622 | private: | ||
623 | std::string mFromName; | ||
611 | }; | 624 | }; |
612 | 625 | ||
613 | class LLOpenTaskOffer : public LLInventoryExistenceObserver | 626 | //unlike the FetchObserver for AgentOffer, we only make one |
627 | //instance of the AddedObserver for TaskOffers | ||
628 | //and it never dies. We do this because we don't know the UUID of | ||
629 | //task offers until they are accepted, so we don't wouldn't | ||
630 | //know what to watch for, so instead we just watch for all additions. -Gigs | ||
631 | class LLOpenTaskOffer : public LLInventoryAddedObserver | ||
614 | { | 632 | { |
615 | public: | ||
616 | LLOpenTaskOffer() {} | ||
617 | virtual ~LLOpenTaskOffer() {} | ||
618 | |||
619 | protected: | 633 | protected: |
620 | virtual void done() | 634 | /*virtual*/ void done() |
621 | { | 635 | { |
622 | open_offer(mExist); | 636 | open_offer(mAdded, ""); |
623 | gInventory.removeObserver(this); | 637 | mAdded.clear(); |
624 | delete this; | ||
625 | } | 638 | } |
626 | }; | 639 | }; |
640 | |||
641 | //one global instance to bind them | ||
642 | LLOpenTaskOffer* gNewInventoryObserver=NULL; | ||
643 | |||
644 | void start_new_inventory_observer() | ||
645 | { | ||
646 | if (!gNewInventoryObserver) //task offer observer | ||
647 | { | ||
648 | // Observer is deleted by gInventory | ||
649 | gNewInventoryObserver = new LLOpenTaskOffer; | ||
650 | gInventory.addObserver(gNewInventoryObserver); | ||
651 | } | ||
652 | } | ||
627 | 653 | ||
628 | class LLDiscardAgentOffer : public LLInventoryFetchComboObserver | 654 | class LLDiscardAgentOffer : public LLInventoryFetchComboObserver |
629 | { | 655 | { |
@@ -675,7 +701,71 @@ protected: | |||
675 | }; | 701 | }; |
676 | 702 | ||
677 | 703 | ||
678 | void open_offer(const std::vector<LLUUID>& items) | 704 | //Returns TRUE if we are OK, FALSE if we are throttled |
705 | //Set check_only true if you want to know the throttle status | ||
706 | //without registering a hit -Gigs | ||
707 | bool check_offer_throttle(const std::string& from_name, bool check_only) | ||
708 | { | ||
709 | static U32 throttle_count; | ||
710 | static bool throttle_logged; | ||
711 | LLChat chat; | ||
712 | LLString log_message; | ||
713 | |||
714 | if (!gSavedSettings.getBOOL("ShowNewInventory")) | ||
715 | return false; | ||
716 | |||
717 | if (check_only) | ||
718 | { | ||
719 | return gThrottleTimer.hasExpired(); | ||
720 | } | ||
721 | |||
722 | if(gThrottleTimer.checkExpirationAndReset(OFFER_THROTTLE_TIME)) | ||
723 | { | ||
724 | //llinfos << "Throttle Expired" << llendl; | ||
725 | throttle_count=1; | ||
726 | throttle_logged=false; | ||
727 | return true; | ||
728 | } | ||
729 | else //has not expired | ||
730 | { | ||
731 | //llinfos << "Throttle Not Expired, Count: " << throttle_count << llendl; | ||
732 | // When downloading the initial inventory we get a lot of new items | ||
733 | // coming in and can't tell that from spam. JC | ||
734 | if (gStartupState >= STATE_STARTED | ||
735 | && throttle_count >= OFFER_THROTTLE_MAX_COUNT) | ||
736 | { | ||
737 | if (!throttle_logged) | ||
738 | { | ||
739 | // Use the name of the last item giver, who is probably the person | ||
740 | // spamming you. JC | ||
741 | std::ostringstream message; | ||
742 | message << gSecondLife; | ||
743 | if (!from_name.empty()) | ||
744 | { | ||
745 | message << ": Items coming in too fast from " << from_name; | ||
746 | } | ||
747 | else | ||
748 | { | ||
749 | message << ": Items coming in too fast"; | ||
750 | } | ||
751 | message << ", automatic preview disabled for " | ||
752 | << OFFER_THROTTLE_TIME << " seconds."; | ||
753 | chat.mText = message.str(); | ||
754 | //this is kinda important, so actually put it on screen | ||
755 | LLFloaterChat::addChat(chat, FALSE, FALSE); | ||
756 | throttle_logged=true; | ||
757 | } | ||
758 | return false; | ||
759 | } | ||
760 | else | ||
761 | { | ||
762 | throttle_count++; | ||
763 | return true; | ||
764 | } | ||
765 | } | ||
766 | } | ||
767 | |||
768 | void open_offer(const std::vector<LLUUID>& items, const std::string& from_name) | ||
679 | { | 769 | { |
680 | std::vector<LLUUID>::const_iterator it = items.begin(); | 770 | std::vector<LLUUID>::const_iterator it = items.begin(); |
681 | std::vector<LLUUID>::const_iterator end = items.end(); | 771 | std::vector<LLUUID>::const_iterator end = items.end(); |
@@ -693,33 +783,66 @@ void open_offer(const std::vector<LLUUID>& items) | |||
693 | { | 783 | { |
694 | continue; | 784 | continue; |
695 | } | 785 | } |
696 | switch(item->getType()) | 786 | //if we are throttled, don't display them - Gigs |
787 | if (check_offer_throttle(from_name, false)) | ||
697 | { | 788 | { |
698 | case LLAssetType::AT_NOTECARD: | 789 | // I'm not sure this is a good idea. JC |
699 | open_notecard(*it, LLString("Note: ") + item->getName(), TRUE, LLUUID::null, FALSE); | 790 | // bool show_keep_discard = item->getPermissions().getCreator() != gAgent.getID(); |
700 | break; | 791 | bool show_keep_discard = true; |
701 | case LLAssetType::AT_LANDMARK: | 792 | switch(item->getType()) |
702 | open_landmark(*it, LLString("Landmark: ") + item->getName(), TRUE, LLUUID::null, FALSE); | ||
703 | break; | ||
704 | case LLAssetType::AT_TEXTURE: | ||
705 | open_texture(*it, LLString("Texture: ") + item->getName(), TRUE, LLUUID::null, FALSE); | ||
706 | break; | ||
707 | default: | ||
708 | { | ||
709 | // Don't auto-open the inventory - just select it if we | ||
710 | // already have an active inventory. | ||
711 | LLInventoryView* view = LLInventoryView::getActiveInventory(); | ||
712 | if(view) | ||
713 | { | 793 | { |
714 | LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); | 794 | case LLAssetType::AT_NOTECARD: |
715 | LLFocusMgr::FocusLostCallback callback; | 795 | open_notecard(*it, LLString("Note: ") + item->getName(), show_keep_discard, LLUUID::null, FALSE); |
716 | callback = gFocusMgr.getFocusCallback(); | 796 | break; |
717 | view->getPanel()->setSelection(item->getUUID(), TAKE_FOCUS_NO); | 797 | case LLAssetType::AT_LANDMARK: |
718 | gFocusMgr.setKeyboardFocus(focus_ctrl, callback); | 798 | open_landmark(*it, LLString("Landmark: ") + item->getName(), show_keep_discard, LLUUID::null, FALSE); |
799 | break; | ||
800 | case LLAssetType::AT_TEXTURE: | ||
801 | open_texture(*it, LLString("Texture: ") + item->getName(), show_keep_discard, LLUUID::null, FALSE); | ||
802 | break; | ||
803 | default: | ||
719 | break; | 804 | break; |
720 | } | 805 | } |
721 | } | 806 | } |
807 | //highlight item, if it's not in the trash or lost+found | ||
808 | |||
809 | // Don't auto-open the inventory floater | ||
810 | LLInventoryView* view = LLInventoryView::getActiveInventory(); | ||
811 | if(!view) | ||
812 | { | ||
813 | return; | ||
814 | } | ||
815 | |||
816 | //Trash Check | ||
817 | LLUUID trash_id; | ||
818 | trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); | ||
819 | if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id)) | ||
820 | { | ||
821 | return; | ||
722 | } | 822 | } |
823 | LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); | ||
824 | //BOOL inventory_has_focus = gFocusMgr.childHasKeyboardFocus(view); | ||
825 | BOOL user_is_away = gAwayTimer.getStarted(); | ||
826 | |||
827 | // don't select lost and found items if the user is active | ||
828 | if (gInventory.isObjectDescendentOf(item->getUUID(), lost_and_found_id) | ||
829 | && !user_is_away) | ||
830 | { | ||
831 | return; | ||
832 | } | ||
833 | |||
834 | //Not sure about this check. Could make it easy to miss incoming items. -Gigs | ||
835 | //don't dick with highlight while the user is working | ||
836 | //if(inventory_has_focus && !user_is_away) | ||
837 | // break; | ||
838 | //llinfos << "Highlighting" << item->getUUID() << llendl; | ||
839 | //highlight item | ||
840 | |||
841 | LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); | ||
842 | LLFocusMgr::FocusLostCallback callback; | ||
843 | callback = gFocusMgr.getFocusCallback(); | ||
844 | view->getPanel()->setSelection(item->getUUID(), TAKE_FOCUS_NO); | ||
845 | gFocusMgr.setKeyboardFocus(focus_ctrl, callback); | ||
723 | } | 846 | } |
724 | } | 847 | } |
725 | 848 | ||
@@ -807,11 +930,11 @@ void inventory_offer_callback(S32 option, void* user_data) | |||
807 | char group_name[MAX_STRING]; /* Flawfinder: ignore */ | 930 | char group_name[MAX_STRING]; /* Flawfinder: ignore */ |
808 | if (gCacheName->getGroupName(info->mFromID, group_name)) | 931 | if (gCacheName->getGroupName(info->mFromID, group_name)) |
809 | { | 932 | { |
810 | from_string = LLString("An object named ") + info->mFromName + " owned by the group '" + group_name + "'"; | 933 | from_string = LLString("An object named '") + info->mFromName + "' owned by the group '" + group_name + "'"; |
811 | } | 934 | } |
812 | else | 935 | else |
813 | { | 936 | { |
814 | from_string = LLString("An object named ") + info->mFromName + " owned by an unknown group"; | 937 | from_string = LLString("An object named '") + info->mFromName + "' owned by an unknown group"; |
815 | } | 938 | } |
816 | } | 939 | } |
817 | else | 940 | else |
@@ -820,11 +943,11 @@ void inventory_offer_callback(S32 option, void* user_data) | |||
820 | char last_name[MAX_STRING]; /* Flawfinder: ignore */ | 943 | char last_name[MAX_STRING]; /* Flawfinder: ignore */ |
821 | if (gCacheName->getName(info->mFromID, first_name, last_name)) | 944 | if (gCacheName->getName(info->mFromID, first_name, last_name)) |
822 | { | 945 | { |
823 | from_string = LLString("An object named ") + info->mFromName + " owned by " + first_name + " " + last_name; | 946 | from_string = LLString("An object named '") + info->mFromName + "' owned by " + first_name + " " + last_name; |
824 | } | 947 | } |
825 | else | 948 | else |
826 | { | 949 | { |
827 | from_string = LLString("An object named ") + info->mFromName + " owned by an unknown user"; | 950 | from_string = LLString("An object named '") + info->mFromName + "' owned by an unknown user"; |
828 | } | 951 | } |
829 | } | 952 | } |
830 | } | 953 | } |
@@ -833,9 +956,11 @@ void inventory_offer_callback(S32 option, void* user_data) | |||
833 | from_string = info->mFromName; | 956 | from_string = info->mFromName; |
834 | } | 957 | } |
835 | 958 | ||
959 | bool busy=FALSE; | ||
960 | |||
836 | switch(option) | 961 | switch(option) |
837 | { | 962 | { |
838 | case 0: | 963 | case IOR_ACCEPT: |
839 | // ACCEPT. The math for the dialog works, because the accept | 964 | // ACCEPT. The math for the dialog works, because the accept |
840 | // for inventory_offered, task_inventory_offer or | 965 | // for inventory_offered, task_inventory_offer or |
841 | // group_notice_inventory is 1 greater than the offer integer value. | 966 | // group_notice_inventory is 1 greater than the offer integer value. |
@@ -846,9 +971,15 @@ void inventory_offer_callback(S32 option, void* user_data) | |||
846 | sizeof(info->mFolderID.mData)); | 971 | sizeof(info->mFolderID.mData)); |
847 | // send the message | 972 | // send the message |
848 | msg->sendReliable(info->mHost); | 973 | msg->sendReliable(info->mHost); |
849 | log_message = info->mFromName + " gave you " + info->mDesc + "."; | 974 | |
850 | chat.mText = log_message; | 975 | //don't spam them if they are getting flooded |
851 | LLFloaterChat::addChatHistory(chat); | 976 | if (check_offer_throttle(info->mFromName, true)) |
977 | { | ||
978 | log_message = info->mFromName + " gave you " + info->mDesc + "."; | ||
979 | chat.mText = log_message; | ||
980 | LLFloaterChat::addChatHistory(chat); | ||
981 | } | ||
982 | |||
852 | // we will want to open this item when it comes back. | 983 | // we will want to open this item when it comes back. |
853 | lldebugs << "Initializing an opener for tid: " << info->mTransactionID | 984 | lldebugs << "Initializing an opener for tid: " << info->mTransactionID |
854 | << llendl; | 985 | << llendl; |
@@ -861,7 +992,7 @@ void inventory_offer_callback(S32 option, void* user_data) | |||
861 | // so we can fetch it out of our inventory. | 992 | // so we can fetch it out of our inventory. |
862 | LLInventoryFetchObserver::item_ref_t items; | 993 | LLInventoryFetchObserver::item_ref_t items; |
863 | items.push_back(info->mObjectID); | 994 | items.push_back(info->mObjectID); |
864 | LLOpenAgentOffer* open_agent_offer = new LLOpenAgentOffer; | 995 | LLOpenAgentOffer* open_agent_offer = new LLOpenAgentOffer(from_string); |
865 | open_agent_offer->fetchItems(items); | 996 | open_agent_offer->fetchItems(items); |
866 | if(catp || (itemp && itemp->isComplete())) | 997 | if(catp || (itemp && itemp->isComplete())) |
867 | { | 998 | { |
@@ -877,22 +1008,10 @@ void inventory_offer_callback(S32 option, void* user_data) | |||
877 | case IM_GROUP_NOTICE: | 1008 | case IM_GROUP_NOTICE: |
878 | case IM_GROUP_NOTICE_REQUESTED: | 1009 | case IM_GROUP_NOTICE_REQUESTED: |
879 | { | 1010 | { |
880 | // This is an offer from a task or group. | 1011 | // This is an offer from a task or group. |
881 | // Because it would be easy | 1012 | // We don't use a new instance of an opener |
882 | // to write a task which would overload your inventory, we | 1013 | // We instead use the singular observer gOpenTaskOffer |
883 | // force the offer to stay in an instant message until | 1014 | // Since it already exists, we don't need to actually do anything |
884 | // accepted. Thus, we have to respond, and then wait for | ||
885 | // the update to come back before we open the item. | ||
886 | LLOpenTaskOffer* open_task_offer = new LLOpenTaskOffer; | ||
887 | open_task_offer->watchItem(info->mObjectID); | ||
888 | if(itemp && itemp->isComplete()) | ||
889 | { | ||
890 | opener->changed(0x0); | ||
891 | } | ||
892 | else | ||
893 | { | ||
894 | opener = open_task_offer; | ||
895 | } | ||
896 | } | 1015 | } |
897 | break; | 1016 | break; |
898 | default: | 1017 | default: |
@@ -901,9 +1020,12 @@ void inventory_offer_callback(S32 option, void* user_data) | |||
901 | } | 1020 | } |
902 | break; | 1021 | break; |
903 | 1022 | ||
904 | case 2: | 1023 | case IOR_BUSY: |
1024 | //Busy falls through to decline. Says to make busy message. | ||
1025 | busy=TRUE; | ||
1026 | case IOR_MUTE: | ||
905 | // MUTE falls through to decline | 1027 | // MUTE falls through to decline |
906 | case 1: | 1028 | case IOR_DECLINE: |
907 | // DECLINE. The math for the dialog works, because the decline | 1029 | // DECLINE. The math for the dialog works, because the decline |
908 | // for inventory_offered, task_inventory_offer or | 1030 | // for inventory_offered, task_inventory_offer or |
909 | // group_notice_inventory is 2 greater than the offer integer value. | 1031 | // group_notice_inventory is 2 greater than the offer integer value. |
@@ -941,7 +1063,7 @@ void inventory_offer_callback(S32 option, void* user_data) | |||
941 | } | 1063 | } |
942 | 1064 | ||
943 | } | 1065 | } |
944 | if (!info->mFromGroup && !info->mFromObject) | 1066 | if (busy || (!info->mFromGroup && !info->mFromObject)) |
945 | { | 1067 | { |
946 | busy_message(msg,info->mFromID); | 1068 | busy_message(msg,info->mFromID); |
947 | } | 1069 | } |
@@ -964,88 +1086,73 @@ void inventory_offer_callback(S32 option, void* user_data) | |||
964 | 1086 | ||
965 | void inventory_offer_handler(LLOfferInfo* info, BOOL from_task) | 1087 | void inventory_offer_handler(LLOfferInfo* info, BOOL from_task) |
966 | { | 1088 | { |
967 | switch(info->mType) | 1089 | |
1090 | //Until throttling is implmented, busy mode should reject inventory instead of silently | ||
1091 | //accepting it. SEE SL-39554 | ||
1092 | if (gAgent.getBusy()) | ||
1093 | { | ||
1094 | inventory_offer_callback(IOR_BUSY, info); | ||
1095 | return; | ||
1096 | } | ||
1097 | |||
1098 | //If muted, don't even go through the messaging stuff. Just curtail the offer here. | ||
1099 | if (gMuteListp->isMuted(info->mFromID, info->mFromName)) | ||
1100 | { | ||
1101 | inventory_offer_callback(IOR_MUTE, info); | ||
1102 | return; | ||
1103 | } | ||
1104 | |||
1105 | if (gSavedSettings.getBOOL("ShowNewInventory") | ||
1106 | && (info->mType == LLAssetType::AT_NOTECARD | ||
1107 | || info->mType == LLAssetType::AT_LANDMARK | ||
1108 | || info->mType == LLAssetType::AT_TEXTURE)) | ||
968 | { | 1109 | { |
969 | // For certain types, just accept the items into the inventory, | 1110 | // For certain types, just accept the items into the inventory, |
970 | // and we'll automatically open them on receipt. | 1111 | // and we'll automatically open them on receipt. |
971 | case LLAssetType::AT_NOTECARD: | 1112 | // 0 = accept button |
972 | case LLAssetType::AT_LANDMARK: | 1113 | inventory_offer_callback(IOR_ACCEPT, info); |
973 | case LLAssetType::AT_TEXTURE: | 1114 | return; |
974 | { | 1115 | } |
975 | // 0 = accept button | 1116 | |
976 | inventory_offer_callback(0, info); | 1117 | LLString::format_map_t args; |
977 | //LLInventoryView::sOpenNextNewItem = TRUE; | 1118 | args["[OBJECTNAME]"] = info->mDesc; |
978 | } | 1119 | args["[OBJECTTYPE]"] = LLAssetType::lookupHumanReadable(info->mType); |
979 | break; | 1120 | |
980 | 1121 | // Name cache callbacks don't store userdata, so can't save | |
981 | case LLAssetType::AT_SOUND: | 1122 | // off the LLOfferInfo. Argh. JC |
982 | case LLAssetType::AT_CALLINGCARD: | 1123 | BOOL name_found = FALSE; |
983 | case LLAssetType::AT_SCRIPT: | 1124 | char first_name[MAX_STRING]; /* Flawfinder: ignore */ |
984 | case LLAssetType::AT_CLOTHING: | 1125 | char last_name[MAX_STRING]; /* Flawfinder: ignore */ |
985 | case LLAssetType::AT_OBJECT: | 1126 | if (info->mFromGroup) |
986 | case LLAssetType::AT_CATEGORY: | 1127 | { |
987 | case LLAssetType::AT_ROOT_CATEGORY: | 1128 | if (gCacheName->getGroupName(info->mFromID, first_name)) |
988 | case LLAssetType::AT_LSL_TEXT: | 1129 | { |
989 | case LLAssetType::AT_LSL_BYTECODE: | 1130 | args["[FIRST]"] = first_name; |
990 | case LLAssetType::AT_TEXTURE_TGA: | 1131 | args["[LAST]"] = ""; |
991 | case LLAssetType::AT_BODYPART: | 1132 | name_found = TRUE; |
992 | case LLAssetType::AT_TRASH: | 1133 | } |
993 | case LLAssetType::AT_SNAPSHOT_CATEGORY: | 1134 | } |
994 | case LLAssetType::AT_LOST_AND_FOUND: | 1135 | else |
995 | case LLAssetType::AT_ANIMATION: | 1136 | { |
996 | case LLAssetType::AT_GESTURE: | 1137 | if (gCacheName->getName(info->mFromID, first_name, last_name)) |
997 | default: | 1138 | { |
998 | { | 1139 | args["[FIRST]"] = first_name; |
999 | LLString::format_map_t args; | 1140 | args["[LAST]"] = last_name; |
1000 | args["[OBJECTNAME]"] = info->mDesc; | 1141 | name_found = TRUE; |
1001 | args["[OBJECTTYPE]"] = LLAssetType::lookupHumanReadable(info->mType); | 1142 | } |
1002 | 1143 | } | |
1003 | // Name cache callbacks don't store userdata, so can't save | 1144 | if (from_task) |
1004 | // off the LLOfferInfo. Argh. JC | 1145 | { |
1005 | BOOL name_found = FALSE; | 1146 | args["[OBJECTFROMNAME]"] = info->mFromName; |
1006 | char first_name[MAX_STRING]; /* Flawfinder: ignore */ | 1147 | LLNotifyBox::showXml(name_found ? "ObjectGiveItem" : "ObjectGiveItemUnknownUser", |
1007 | char last_name[MAX_STRING]; /* Flawfinder: ignore */ | 1148 | args, &inventory_offer_callback, (void*)info); |
1008 | if (info->mFromGroup) | 1149 | } |
1009 | { | 1150 | else |
1010 | if (gCacheName->getGroupName(info->mFromID, first_name)) | 1151 | { |
1011 | { | 1152 | // XUI:translate -> [FIRST] [LAST] |
1012 | args["[FIRST]"] = first_name; | 1153 | args["[NAME]"] = info->mFromName; |
1013 | args["[LAST]"] = ""; | 1154 | LLNotifyBox::showXml("UserGiveItem", args, |
1014 | name_found = TRUE; | 1155 | &inventory_offer_callback, (void*)info); |
1015 | } | ||
1016 | } | ||
1017 | else | ||
1018 | { | ||
1019 | if (gCacheName->getName(info->mFromID, first_name, last_name)) | ||
1020 | { | ||
1021 | args["[FIRST]"] = first_name; | ||
1022 | args["[LAST]"] = last_name; | ||
1023 | name_found = TRUE; | ||
1024 | } | ||
1025 | } | ||
1026 | if (from_task) | ||
1027 | { | ||
1028 | args["[OBJECTFROMNAME]"] = info->mFromName; | ||
1029 | if (name_found) | ||
1030 | { | ||
1031 | LLNotifyBox::showXml("ObjectGiveItem", args, | ||
1032 | &inventory_offer_callback, (void*)info); | ||
1033 | } | ||
1034 | else | ||
1035 | { | ||
1036 | LLNotifyBox::showXml("ObjectGiveItemUnknownUser", args, | ||
1037 | &inventory_offer_callback, (void*)info); | ||
1038 | } | ||
1039 | } | ||
1040 | else | ||
1041 | { | ||
1042 | // XUI:translate -> [FIRST] [LAST] | ||
1043 | args["[NAME]"] = info->mFromName; | ||
1044 | LLNotifyBox::showXml("UserGiveItem", args, | ||
1045 | &inventory_offer_callback, (void*)info); | ||
1046 | } | ||
1047 | break; | ||
1048 | } | ||
1049 | } | 1156 | } |
1050 | } | 1157 | } |
1051 | 1158 | ||
@@ -1538,10 +1645,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) | |||
1538 | } | 1645 | } |
1539 | else | 1646 | else |
1540 | { | 1647 | { |
1541 | if (dialog == IM_TASK_INVENTORY_OFFERED) | 1648 | inventory_offer_handler(info, dialog == IM_TASK_INVENTORY_OFFERED); |
1542 | inventory_offer_handler(info, TRUE); | ||
1543 | else | ||
1544 | inventory_offer_handler(info, FALSE); | ||
1545 | } | 1649 | } |
1546 | } | 1650 | } |
1547 | break; | 1651 | break; |
@@ -1760,6 +1864,14 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) | |||
1760 | 1864 | ||
1761 | case IM_GOTO_URL: | 1865 | case IM_GOTO_URL: |
1762 | { | 1866 | { |
1867 | if (binary_bucket_size <= 0) | ||
1868 | { | ||
1869 | llwarns << "bad binary_bucket_size: " | ||
1870 | << binary_bucket_size | ||
1871 | << " - aborting function." << llendl; | ||
1872 | return; | ||
1873 | } | ||
1874 | |||
1763 | char* url = new char[binary_bucket_size]; | 1875 | char* url = new char[binary_bucket_size]; |
1764 | if (url == NULL) | 1876 | if (url == NULL) |
1765 | { | 1877 | { |
@@ -1985,16 +2097,22 @@ void process_offer_callingcard(LLMessageSystem* msg, void**) | |||
1985 | { | 2097 | { |
1986 | // automatically decline offer | 2098 | // automatically decline offer |
1987 | callingcard_offer_callback(1, (void*)offerdata); | 2099 | callingcard_offer_callback(1, (void*)offerdata); |
1988 | return; | 2100 | offerdata = NULL; // pointer was freed by callback |
2101 | } | ||
2102 | else | ||
2103 | { | ||
2104 | LLNotifyBox::showXml("OfferCallingCard", args, | ||
2105 | &callingcard_offer_callback, (void*)offerdata); | ||
2106 | offerdata = NULL; // pointer ownership transferred | ||
1989 | } | 2107 | } |
1990 | |||
1991 | LLNotifyBox::showXml("OfferCallingCard", args, | ||
1992 | &callingcard_offer_callback, (void*)offerdata); | ||
1993 | } | 2108 | } |
1994 | else | 2109 | else |
1995 | { | 2110 | { |
1996 | llwarns << "Calling card offer from an unknown source." << llendl; | 2111 | llwarns << "Calling card offer from an unknown source." << llendl; |
1997 | } | 2112 | } |
2113 | |||
2114 | delete offerdata; // !=NULL if we didn't give ownership away | ||
2115 | offerdata = NULL; | ||
1998 | } | 2116 | } |
1999 | 2117 | ||
2000 | void process_accept_callingcard(LLMessageSystem* msg, void**) | 2118 | void process_accept_callingcard(LLMessageSystem* msg, void**) |
@@ -3609,7 +3727,7 @@ void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data) | |||
3609 | if (object) | 3727 | if (object) |
3610 | { | 3728 | { |
3611 | LLVector3 sit_spot = object->getPositionAgent() + (sitPosition * object->getRotation()); | 3729 | LLVector3 sit_spot = object->getPositionAgent() + (sitPosition * object->getRotation()); |
3612 | if (!use_autopilot || (avatar->mIsSitting && avatar->getRoot() == object->getRoot())) | 3730 | if (!use_autopilot || (avatar && avatar->mIsSitting && avatar->getRoot() == object->getRoot())) |
3613 | { | 3731 | { |
3614 | //we're already sitting on this object, so don't autopilot | 3732 | //we're already sitting on this object, so don't autopilot |
3615 | } | 3733 | } |
@@ -5002,9 +5120,10 @@ void onCovenantLoadComplete(LLVFS *vfs, | |||
5002 | 5120 | ||
5003 | if( (file_length > 19) && !strncmp( buffer, "Linden text version", 19 ) ) | 5121 | if( (file_length > 19) && !strncmp( buffer, "Linden text version", 19 ) ) |
5004 | { | 5122 | { |
5005 | LLViewerTextEditor* editor = new LLViewerTextEditor("temp", | 5123 | LLViewerTextEditor* editor = |
5006 | LLRect(0,0,0,0), | 5124 | new LLViewerTextEditor("temp", |
5007 | file_length+1); | 5125 | LLRect(0,0,0,0), |
5126 | file_length+1); | ||
5008 | if( !editor->importBuffer( buffer ) ) | 5127 | if( !editor->importBuffer( buffer ) ) |
5009 | { | 5128 | { |
5010 | llwarns << "Problem importing estate covenant." << llendl; | 5129 | llwarns << "Problem importing estate covenant." << llendl; |
@@ -5020,27 +5139,32 @@ void onCovenantLoadComplete(LLVFS *vfs, | |||
5020 | } | 5139 | } |
5021 | else | 5140 | else |
5022 | { | 5141 | { |
5023 | if( gViewerStats ) | 5142 | llwarns << "Problem importing estate covenant: Covenant file format error." << llendl; |
5024 | { | 5143 | covenant_text = "Problem importing estate covenant: Covenant file format error."; |
5025 | gViewerStats->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); | 5144 | } |
5026 | } | 5145 | } |
5027 | 5146 | else | |
5028 | if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || | 5147 | { |
5029 | LL_ERR_FILE_EMPTY == status) | 5148 | if( gViewerStats ) |
5030 | { | 5149 | { |
5031 | covenant_text = "Estate covenant notecard is missing from database."; | 5150 | gViewerStats->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); |
5032 | } | ||
5033 | else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) | ||
5034 | { | ||
5035 | covenant_text = "Insufficient permissions to view estate covenant."; | ||
5036 | } | ||
5037 | else | ||
5038 | { | ||
5039 | covenant_text = "Unable to load estate covenant at this time."; | ||
5040 | } | ||
5041 | |||
5042 | llwarns << "Problem loading notecard: " << status << llendl; | ||
5043 | } | 5151 | } |
5152 | |||
5153 | if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || | ||
5154 | LL_ERR_FILE_EMPTY == status) | ||
5155 | { | ||
5156 | covenant_text = "Estate covenant notecard is missing from database."; | ||
5157 | } | ||
5158 | else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) | ||
5159 | { | ||
5160 | covenant_text = "Insufficient permissions to view estate covenant."; | ||
5161 | } | ||
5162 | else | ||
5163 | { | ||
5164 | covenant_text = "Unable to load estate covenant at this time."; | ||
5165 | } | ||
5166 | |||
5167 | llwarns << "Problem loading notecard: " << status << llendl; | ||
5044 | } | 5168 | } |
5045 | LLPanelEstateCovenant::updateCovenantText(covenant_text, asset_uuid); | 5169 | LLPanelEstateCovenant::updateCovenantText(covenant_text, asset_uuid); |
5046 | LLPanelLandCovenant::updateCovenantText(covenant_text); | 5170 | LLPanelLandCovenant::updateCovenantText(covenant_text); |