aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llviewerparcelmedia.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/newview/llviewerparcelmedia.cpp')
-rw-r--r--linden/indra/newview/llviewerparcelmedia.cpp273
1 files changed, 219 insertions, 54 deletions
diff --git a/linden/indra/newview/llviewerparcelmedia.cpp b/linden/indra/newview/llviewerparcelmedia.cpp
index a5d97f2..386a86e 100644
--- a/linden/indra/newview/llviewerparcelmedia.cpp
+++ b/linden/indra/newview/llviewerparcelmedia.cpp
@@ -49,6 +49,7 @@
49#include "llpluginclassmedia.h" 49#include "llpluginclassmedia.h"
50#include "llnotify.h" 50#include "llnotify.h"
51#include "llsdserialize.h" 51#include "llsdserialize.h"
52#include "llmemory.h"
52 53
53#include "lloverlaybar.h" 54#include "lloverlaybar.h"
54#include "slfloatermediafilter.h" 55#include "slfloatermediafilter.h"
@@ -64,6 +65,7 @@ LLSD LLViewerParcelMedia::sMediaFilterList;
64std::set<std::string> LLViewerParcelMedia::sMediaQueries; 65std::set<std::string> LLViewerParcelMedia::sMediaQueries;
65std::set<std::string> LLViewerParcelMedia::sAllowedMedia; 66std::set<std::string> LLViewerParcelMedia::sAllowedMedia;
66std::set<std::string> LLViewerParcelMedia::sDeniedMedia; 67std::set<std::string> LLViewerParcelMedia::sDeniedMedia;
68LLPointer<LLViewerParcelMediaInfo> LLViewerParcelMedia::sSavedMediaInfo;
67 69
68// Local functions 70// Local functions
69bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel); 71bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel);
@@ -186,7 +188,7 @@ void LLViewerParcelMedia::update(LLParcel* parcel)
186} 188}
187 189
188// static 190// static
189void LLViewerParcelMedia::play(LLParcel* parcel, bool filter) 191void LLViewerParcelMedia::play(LLParcel* parcel, bool filter, const ECommandOrigin origin)
190{ 192{
191 lldebugs << "LLViewerParcelMedia::play" << llendl; 193 lldebugs << "LLViewerParcelMedia::play" << llendl;
192 194
@@ -198,12 +200,13 @@ void LLViewerParcelMedia::play(LLParcel* parcel, bool filter)
198 std::string media_url = parcel->getMediaURL(); 200 std::string media_url = parcel->getMediaURL();
199 LLStringUtil::trim(media_url); 201 LLStringUtil::trim(media_url);
200 202
201 if (!media_url.empty() && gSavedSettings.getBOOL("MediaEnableFilter") && (filter || !allowedMedia(media_url))) 203 if (!media_url.empty() && gSavedSettings.getBOOL("MediaEnableFilter") && filter
204 && (!allowedMedia(media_url) || origin == COMMAND_ORIGIN_REMOTE))
202 { 205 {
203 // If filtering is needed or in case media_url just changed 206 // If filtering is needed or in case media_url just changed
204 // to something we did not yet approve. 207 // to something we did not yet approve.
205 LLViewerParcelMediaAutoPlay::playStarted(); 208 LLViewerParcelMediaAutoPlay::playStarted();
206 filterMedia(parcel, 0); 209 filterMedia(parcel, 0, origin);
207 return; 210 return;
208 } 211 }
209 212
@@ -384,7 +387,7 @@ void LLViewerParcelMedia::processParcelMediaCommandMessage( LLMessageSystem *msg
384 else 387 else
385 { 388 {
386 LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); 389 LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
387 play(parcel); 390 play(parcel, true, COMMAND_ORIGIN_REMOTE);
388 } 391 }
389 } 392 }
390 else 393 else
@@ -400,7 +403,7 @@ void LLViewerParcelMedia::processParcelMediaCommandMessage( LLMessageSystem *msg
400 if(sMediaImpl.isNull()) 403 if(sMediaImpl.isNull())
401 { 404 {
402 LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); 405 LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
403 play(parcel); 406 play(parcel, true, COMMAND_ORIGIN_REMOTE);
404 } 407 }
405 seek(time); 408 seek(time);
406 } 409 }
@@ -437,33 +440,38 @@ void LLViewerParcelMedia::processParcelMediaUpdate( LLMessageSystem *msg, void *
437 } 440 }
438 441
439 LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); 442 LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
440 BOOL same = FALSE;
441 if (parcel) 443 if (parcel)
442 { 444 {
443 same = ((parcel->getMediaURL() == media_url) && 445 LLViewerParcelMediaInfo* new_info = new LLViewerParcelMediaInfo(media_url, media_type, media_id, media_width, media_height, media_auto_scale, media_loop);
444 (parcel->getMediaType() == media_type) && 446 LLViewerParcelMediaInfo* current_info = new LLViewerParcelMediaInfo(parcel);
445 (parcel->getMediaID() == media_id) && 447 if (new_info != current_info)
446 (parcel->getMediaWidth() == media_width) &&
447 (parcel->getMediaHeight() == media_height) &&
448 (parcel->getMediaAutoScale() == media_auto_scale) &&
449 (parcel->getMediaLoop() == media_loop));
450
451 if (!same)
452 { 448 {
449 if (!sSavedMediaInfo || (sSavedMediaInfo && !sSavedMediaInfo->sameParcel(parcel)))
450 {
451 // only save if no previously saved media info, because
452 // we want to remeber the original parcel media info.
453 sSavedMediaInfo = current_info;
454 }
453 // temporarily store these new values in the parcel 455 // temporarily store these new values in the parcel
454 parcel->setMediaURL(media_url); 456 new_info->applyToParcel(parcel);
455 parcel->setMediaType(media_type);
456 parcel->setMediaID(media_id);
457 parcel->setMediaWidth(media_width);
458 parcel->setMediaHeight(media_height);
459 parcel->setMediaAutoScale(media_auto_scale);
460 parcel->setMediaLoop(media_loop);
461 457
462 play(parcel); 458 play(parcel, true, COMMAND_ORIGIN_REMOTE);
463 } 459 }
464 460
465 } 461 }
466} 462}
463
464//static
465void LLViewerParcelMedia::undoParcelMediaUpdate()
466{
467 LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
468 if (sSavedMediaInfo.notNull() && parcel)
469 {
470 sSavedMediaInfo->applyToParcel(parcel);
471 }
472 sSavedMediaInfo = NULL;
473}
474
467// Static 475// Static
468///////////////////////////////////////////////////////////////////////////////////////// 476/////////////////////////////////////////////////////////////////////////////////////////
469void LLViewerParcelMedia::sendMediaNavigateMessage(const std::string& url) 477void LLViewerParcelMedia::sendMediaNavigateMessage(const std::string& url)
@@ -619,7 +627,7 @@ void LLViewerParcelMedia::playStreamingMusic(LLParcel* parcel, bool filter)
619 { 627 {
620 // If filtering is needed or in case music_url just changed 628 // If filtering is needed or in case music_url just changed
621 // to something we did not yet approve. 629 // to something we did not yet approve.
622 filterMedia(parcel, 1); 630 filterMedia(parcel, 1, COMMAND_ORIGIN_LOCAL);
623 } 631 }
624 else if (gAudioStream) 632 else if (gAudioStream)
625 { 633 {
@@ -649,13 +657,18 @@ bool LLViewerParcelMedia::allowedMedia(std::string media_url)
649{ 657{
650 LLStringUtil::trim(media_url); 658 LLStringUtil::trim(media_url);
651 std::string domain = extractDomain(media_url); 659 std::string domain = extractDomain(media_url);
660 LLHost host;
661 host.setHostByName(domain);
662 std::string ip = host.getIPString();
652 if (sAllowedMedia.count(domain)) 663 if (sAllowedMedia.count(domain))
653 { 664 {
654 return true; 665 return true;
655 } 666 }
667 std::string server;
656 for (S32 i = 0; i < (S32)sMediaFilterList.size(); i++) 668 for (S32 i = 0; i < (S32)sMediaFilterList.size(); i++)
657 { 669 {
658 if (sMediaFilterList[i]["domain"].asString() == domain) 670 server = sMediaFilterList[i]["domain"].asString();
671 if (server == domain || server == ip)
659 { 672 {
660 if (sMediaFilterList[i]["action"].asString() == "allow") 673 if (sMediaFilterList[i]["action"].asString() == "allow")
661 { 674 {
@@ -670,12 +683,13 @@ bool LLViewerParcelMedia::allowedMedia(std::string media_url)
670 return false; 683 return false;
671} 684}
672 685
673void LLViewerParcelMedia::filterMedia(LLParcel* parcel, U32 type) 686void LLViewerParcelMedia::filterMedia(LLParcel* parcel, U32 type, const ECommandOrigin origin)
674{ 687{
675 std::string media_action; 688 std::string media_action;
676 std::string media_url; 689 std::string media_url;
677 std::string domain; 690 std::string domain;
678 691 std::string ip;
692
679 if (parcel != LLViewerParcelMgr::getInstance()->getAgentParcel()) 693 if (parcel != LLViewerParcelMgr::getInstance()->getAgentParcel())
680 { 694 {
681 // The parcel just changed (may occur right out after a TP) 695 // The parcel just changed (may occur right out after a TP)
@@ -703,31 +717,51 @@ void LLViewerParcelMedia::filterMedia(LLParcel* parcel, U32 type)
703 return; 717 return;
704 } 718 }
705 719
720 LLHost host;
721 host.setHostByName(domain);
722 ip = host.getIPString();
723
706 if (sIsUserAction) 724 if (sIsUserAction)
707 { 725 {
708 // This was a user manual request to play this media, so give 726 // This was a user manual request to play this media, so give
709 // it another chance... 727 // it another chance...
710 sIsUserAction = false; 728 sIsUserAction = false;
729 bool dirty = false;
711 if (sDeniedMedia.count(domain)) 730 if (sDeniedMedia.count(domain))
712 { 731 {
713 sDeniedMedia.erase(domain); 732 sDeniedMedia.erase(domain);
733 dirty = true;
734 }
735 if (sDeniedMedia.count(ip))
736 {
737 sDeniedMedia.erase(ip);
738 dirty = true;
739 }
740 if (dirty)
741 {
714 SLFloaterMediaFilter::setDirty(); 742 SLFloaterMediaFilter::setDirty();
715 } 743 }
716 } 744 }
717 745
718 if (!sMediaFilterListLoaded || sDeniedMedia.count(domain)) 746 if (media_url.empty())
747 {
748 media_action == "allow";
749 }
750 else if (!sMediaFilterListLoaded || sDeniedMedia.count(domain) || sDeniedMedia.count(ip))
719 { 751 {
720 media_action = "ignore"; 752 media_action = "ignore";
721 } 753 }
722 else if (sAllowedMedia.count(domain)) 754 else if (sAllowedMedia.count(domain) || sAllowedMedia.count(ip))
723 { 755 {
724 media_action = "allow"; 756 media_action = "allow";
725 } 757 }
726 else 758 else
727 { 759 {
760 std::string server;
728 for (S32 i = 0; i < (S32)sMediaFilterList.size(); i++) 761 for (S32 i = 0; i < (S32)sMediaFilterList.size(); i++)
729 { 762 {
730 if (sMediaFilterList[i]["domain"].asString() == domain) 763 server = sMediaFilterList[i]["domain"].asString();
764 if (server == domain || server == ip)
731 { 765 {
732 media_action = sMediaFilterList[i]["action"].asString(); 766 media_action = sMediaFilterList[i]["action"].asString();
733 break; 767 break;
@@ -735,7 +769,7 @@ void LLViewerParcelMedia::filterMedia(LLParcel* parcel, U32 type)
735 } 769 }
736 } 770 }
737 771
738 if (media_action == "allow" || media_url.empty()) 772 if (media_action == "allow")
739 { 773 {
740 if (type == 0) 774 if (type == 0)
741 { 775 {
@@ -745,47 +779,76 @@ void LLViewerParcelMedia::filterMedia(LLParcel* parcel, U32 type)
745 { 779 {
746 playStreamingMusic(parcel, false); 780 playStreamingMusic(parcel, false);
747 } 781 }
782 return;
748 } 783 }
749 else if (media_action == "deny") 784 if (media_action == "ignore")
750 { 785 {
751 LLSD args; 786 if (type == 0)
752 args["DOMAIN"] = domain; 787 {
753 LLNotifications::instance().add("MediaBlocked", args); 788 undoParcelMediaUpdate();
754 if (type == 1) 789 }
790 else if (type == 1)
755 { 791 {
756 LLViewerParcelMedia::stopStreamingMusic(); 792 LLViewerParcelMedia::stopStreamingMusic();
757 } 793 }
758 // So to avoid other "blocked" messages later in the session 794 return;
759 // for this url should it be requested again by a script.
760 sDeniedMedia.insert(domain);
761 } 795 }
762 else if (media_action == "ignore") 796 // skip local-originating play commands, unless the url is blacklisted.
797 if (gSavedSettings.getBOOL("MediaFilterOnlyRemoteCommands")
798 && (origin != COMMAND_ORIGIN_REMOTE)
799 && (media_action != "ignore"))
763 { 800 {
764 if (type == 1) 801 sAllowedMedia.insert(domain);
802 SLFloaterMediaFilter::setDirty();
803 if (type == 0)
765 { 804 {
766 LLViewerParcelMedia::stopStreamingMusic(); 805 play(parcel, false);
767 } 806 }
807 else
808 {
809 playStreamingMusic(parcel, false);
810 }
811 return;
812 }
813
814 LLSD args;
815 if (ip != domain && domain.find('/') == std::string::npos)
816 {
817 args["DOMAIN"] = domain + " (" + ip + ")";
768 } 818 }
769 else 819 else
770 { 820 {
771 sMediaQueries.insert(domain);
772 LLSD args;
773 args["DOMAIN"] = domain; 821 args["DOMAIN"] = domain;
774 if (media_url.find('?') != std::string::npos) 822 }
823
824 if (media_action == "deny")
825 {
826 LLNotifications::instance().add("MediaBlocked", args);
827 if (type == 0)
775 { 828 {
776 args["WARNING"] = " (WARNING: this URL also contains parameter(s) that could potentially be used to correlate your avatar name with your IP)"; 829 undoParcelMediaUpdate();
777 } 830 }
778 else 831 if (type == 1)
779 { 832 {
780 args["WARNING"] = ""; 833 LLViewerParcelMedia::stopStreamingMusic();
781 } 834 }
835 // So to avoid other "blocked" messages later in the session
836 // for this url should it be requested again by a script.
837 // We don't add the IP, on purpose (want to show different
838 // blocks for different domains pointing to the same IP).
839 sDeniedMedia.insert(domain);
840 }
841 else
842 {
843 sMediaQueries.insert(domain);
844 args["URL"] = media_url;
782 if (type == 0) 845 if (type == 0)
783 { 846 {
784 args["TYPE"] = "a media"; 847 args["TYPE"] = "media";
785 } 848 }
786 else 849 else
787 { 850 {
788 args["TYPE"] = "an audio"; 851 args["TYPE"] = "audio";
789 } 852 }
790 LLNotifications::instance().add("MediaAlert", args, LLSD(), boost::bind(callback_media_alert, _1, _2, parcel, type, domain)); 853 LLNotifications::instance().add("MediaAlert", args, LLSD(), boost::bind(callback_media_alert, _1, _2, parcel, type, domain));
791 } 854 }
@@ -795,8 +858,19 @@ void callback_media_alert(const LLSD &notification, const LLSD &response, LLParc
795{ 858{
796 S32 option = LLNotification::getSelectedOption(notification, response); 859 S32 option = LLNotification::getSelectedOption(notification, response);
797 860
861 LLHost host;
862 host.setHostByName(domain);
863 std::string ip = host.getIPString();
864
798 LLSD args; 865 LLSD args;
799 args["DOMAIN"] = domain; 866 if (ip != domain && domain.find('/') == std::string::npos)
867 {
868 args["DOMAIN"] = domain + " (" + ip + ")";
869 }
870 else
871 {
872 args["DOMAIN"] = domain;
873 }
800 874
801 if (option == 0 || option == 3) // Allow or Whitelist 875 if (option == 0 || option == 3) // Allow or Whitelist
802 { 876 {
@@ -807,6 +881,11 @@ void callback_media_alert(const LLSD &notification, const LLSD &response, LLParc
807 newmedia["domain"] = domain; 881 newmedia["domain"] = domain;
808 newmedia["action"] = "allow"; 882 newmedia["action"] = "allow";
809 LLViewerParcelMedia::sMediaFilterList.append(newmedia); 883 LLViewerParcelMedia::sMediaFilterList.append(newmedia);
884 if (ip != domain && domain.find('/') == std::string::npos)
885 {
886 newmedia["domain"] = ip;
887 LLViewerParcelMedia::sMediaFilterList.append(newmedia);
888 }
810 LLViewerParcelMedia::saveDomainFilterList(); 889 LLViewerParcelMedia::saveDomainFilterList();
811 args["LISTED"] = "whitelisted"; 890 args["LISTED"] = "whitelisted";
812 LLNotifications::instance().add("MediaListed", args); 891 LLNotifications::instance().add("MediaListed", args);
@@ -823,10 +902,19 @@ void callback_media_alert(const LLSD &notification, const LLSD &response, LLParc
823 else if (option == 1 || option == 2) // Deny or Blacklist 902 else if (option == 1 || option == 2) // Deny or Blacklist
824 { 903 {
825 LLViewerParcelMedia::sDeniedMedia.insert(domain); 904 LLViewerParcelMedia::sDeniedMedia.insert(domain);
826 if (type == 1) 905 if (ip != domain && domain.find('/') == std::string::npos)
906 {
907 LLViewerParcelMedia::sDeniedMedia.insert(ip);
908 }
909 if (type == 0)
910 {
911 LLViewerParcelMedia::undoParcelMediaUpdate();
912 }
913 else if (type == 1)
827 { 914 {
828 LLViewerParcelMedia::stopStreamingMusic(); 915 LLViewerParcelMedia::stopStreamingMusic();
829 } 916 }
917
830 if (option == 1) // Deny 918 if (option == 1) // Deny
831 { 919 {
832 LLNotifications::instance().add("MediaBlocked", args); 920 LLNotifications::instance().add("MediaBlocked", args);
@@ -837,6 +925,11 @@ void callback_media_alert(const LLSD &notification, const LLSD &response, LLParc
837 newmedia["domain"] = domain; 925 newmedia["domain"] = domain;
838 newmedia["action"] = "deny"; 926 newmedia["action"] = "deny";
839 LLViewerParcelMedia::sMediaFilterList.append(newmedia); 927 LLViewerParcelMedia::sMediaFilterList.append(newmedia);
928 if (ip != domain && domain.find('/') == std::string::npos)
929 {
930 newmedia["domain"] = ip;
931 LLViewerParcelMedia::sMediaFilterList.append(newmedia);
932 }
840 LLViewerParcelMedia::saveDomainFilterList(); 933 LLViewerParcelMedia::saveDomainFilterList();
841 args["LISTED"] = "blacklisted"; 934 args["LISTED"] = "blacklisted";
842 LLNotifications::instance().add("MediaListed", args); 935 LLNotifications::instance().add("MediaListed", args);
@@ -928,7 +1021,12 @@ std::string LLViewerParcelMedia::extractDomain(std::string url)
928 url = url.substr(pos + 1, count); 1021 url = url.substr(pos + 1, count);
929 } 1022 }
930 1023
931 if (url.find(gAgent.getRegion()->getHost().getHostName()) == 0 || url.find(last_region) == 0) 1024 std::string current_region = gAgent.getRegion()->getHost().getHostName();
1025 if (!current_region.size())
1026 {
1027 current_region = gAgent.getRegion()->getHost().getIPString();
1028 }
1029 if (url.find(current_region) == 0 || url.find(last_region) == 0)
932 { 1030 {
933 // This must be a scripted object rezzed in the region: 1031 // This must be a scripted object rezzed in the region:
934 // extend the concept of "domain" to encompass the 1032 // extend the concept of "domain" to encompass the
@@ -937,7 +1035,7 @@ std::string LLViewerParcelMedia::extractDomain(std::string url)
937 1035
938 // Get rid of any port number 1036 // Get rid of any port number
939 pos = url.find('/'); // We earlier made sure that there's one 1037 pos = url.find('/'); // We earlier made sure that there's one
940 url = gAgent.getRegion()->getHost().getHostName() + url.substr(pos); 1038 url = current_region + url.substr(pos);
941 1039
942 pos = url.find('?'); 1040 pos = url.find('?');
943 if (pos != std::string::npos) 1041 if (pos != std::string::npos)
@@ -972,6 +1070,73 @@ std::string LLViewerParcelMedia::extractDomain(std::string url)
972 // Remember this region, so to cope with requests occuring just after a 1070 // Remember this region, so to cope with requests occuring just after a
973 // TP out of it. 1071 // TP out of it.
974 last_region = gAgent.getRegion()->getHost().getHostName(); 1072 last_region = gAgent.getRegion()->getHost().getHostName();
1073 if (!last_region.size())
1074 {
1075 last_region = gAgent.getRegion()->getHost().getIPString();
1076 }
975 1077
976 return url; 1078 return url;
977} 1079}
1080
1081LLViewerParcelMediaInfo::LLViewerParcelMediaInfo(const std::string url,
1082 const std::string type,
1083 const LLUUID media_id,
1084 const S32 width,
1085 const S32 height,
1086 const U8 scale,
1087 const U8 loop)
1088 :
1089 mMediaURL(url),
1090 mMediaType(type),
1091 mMediaID(media_id),
1092 mMediaWidth(width),
1093 mMediaHeight(height),
1094 mMediaAutoScale(scale),
1095 mMediaLoop(loop)
1096{
1097 LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
1098 mParcelLocalID = parcel ? parcel->getLocalID() : 0;
1099}
1100
1101LLViewerParcelMediaInfo::LLViewerParcelMediaInfo(const LLParcel* parcel)
1102{
1103 mMediaURL = parcel->getMediaURL();
1104 mMediaType = parcel->getMediaType();
1105 mMediaID = parcel->getMediaID();
1106 mMediaWidth = parcel->getMediaWidth();
1107 mMediaHeight = parcel->getMediaHeight();
1108 mMediaAutoScale = parcel->getMediaAutoScale();
1109 mMediaLoop = parcel->getMediaLoop();
1110 mParcelLocalID = parcel->getLocalID();
1111}
1112
1113void LLViewerParcelMediaInfo::applyToParcel(LLParcel* parcel)
1114{
1115 if (parcel && sameParcel(parcel))
1116 {
1117 parcel->setMediaURL(mMediaURL);
1118 parcel->setMediaType(mMediaType);
1119 parcel->setMediaID(mMediaID);
1120 parcel->setMediaWidth(mMediaWidth);
1121 parcel->setMediaHeight(mMediaHeight);
1122 parcel->setMediaAutoScale(mMediaAutoScale);
1123 parcel->setMediaLoop(mMediaLoop);
1124 }
1125}
1126
1127bool LLViewerParcelMediaInfo::sameParcel(const LLParcel* parcel) const
1128{
1129 return parcel && (parcel->getLocalID() == mParcelLocalID);
1130}
1131
1132bool LLViewerParcelMediaInfo::operator==(const LLViewerParcelMediaInfo &rhs) const
1133{
1134 return (mMediaURL == rhs.mMediaURL) &&
1135 (mMediaType == rhs.mMediaType) &&
1136 (mMediaID == rhs.mMediaID) &&
1137 (mMediaWidth == rhs.mMediaWidth) &&
1138 (mMediaHeight == rhs.mMediaHeight) &&
1139 (mMediaAutoScale == rhs.mMediaAutoScale) &&
1140 (mMediaLoop == rhs.mMediaLoop) &&
1141 (mParcelLocalID == rhs.mParcelLocalID);
1142} \ No newline at end of file