aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/CMakeLists.txt2
-rw-r--r--linden/indra/newview/app_settings/logcontrol.xml1
-rw-r--r--linden/indra/newview/app_settings/settings.xml27
-rw-r--r--linden/indra/newview/lloverlaybar.cpp21
-rw-r--r--linden/indra/newview/lloverlaybar.h4
-rw-r--r--linden/indra/newview/llstartup.cpp2
-rw-r--r--linden/indra/newview/llviewercontrol.cpp3
-rw-r--r--linden/indra/newview/llviewermenu.cpp9
-rw-r--r--linden/indra/newview/llviewerparcelmedia.cpp397
-rw-r--r--linden/indra/newview/llviewerparcelmedia.h24
-rw-r--r--linden/indra/newview/llviewerparcelmgr.cpp12
-rw-r--r--linden/indra/newview/skins/default/xui/en-us/floater_media_filter.xml61
-rw-r--r--linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml5
-rw-r--r--linden/indra/newview/skins/default/xui/en-us/notifications.xml50
-rw-r--r--linden/indra/newview/slfloatermediafilter.cpp350
-rw-r--r--linden/indra/newview/slfloatermediafilter.h70
16 files changed, 1025 insertions, 13 deletions
diff --git a/linden/indra/newview/CMakeLists.txt b/linden/indra/newview/CMakeLists.txt
index dedced0..9a4e2ed 100644
--- a/linden/indra/newview/CMakeLists.txt
+++ b/linden/indra/newview/CMakeLists.txt
@@ -498,6 +498,7 @@ set(viewer_SOURCE_FILES
498 rlvmultistringsearch.cpp 498 rlvmultistringsearch.cpp
499 rlvextensions.cpp 499 rlvextensions.cpp
500 rlvfloaterbehaviour.cpp 500 rlvfloaterbehaviour.cpp
501 slfloatermediafilter.cpp
501 viewertime.cpp 502 viewertime.cpp
502 viewerversion.cpp 503 viewerversion.cpp
503 windlightsettingsupdate.cpp 504 windlightsettingsupdate.cpp
@@ -967,6 +968,7 @@ set(viewer_HEADER_FILES
967 rlvmultistringsearch.h 968 rlvmultistringsearch.h
968 rlvextensions.h 969 rlvextensions.h
969 rlvfloaterbehaviour.h 970 rlvfloaterbehaviour.h
971 slfloatermediafilter.h
970 VertexCache.h 972 VertexCache.h
971 VorbisFramework.h 973 VorbisFramework.h
972 viewertime.h 974 viewertime.h
diff --git a/linden/indra/newview/app_settings/logcontrol.xml b/linden/indra/newview/app_settings/logcontrol.xml
index 51bb456..c9e9127 100644
--- a/linden/indra/newview/app_settings/logcontrol.xml
+++ b/linden/indra/newview/app_settings/logcontrol.xml
@@ -58,6 +58,7 @@
58 <!--<string>HUDEffect</string>--> 58 <!--<string>HUDEffect</string>-->
59 <!--<string>MarkerFile</string>--> 59 <!--<string>MarkerFile</string>-->
60 <!--<string>Media</string>--> 60 <!--<string>Media</string>-->
61 <string>MediaFilter</string>
61 <!--<string>MediaInfo</string>--> 62 <!--<string>MediaInfo</string>-->
62 <!--<string>MediaCallback</string>--> 63 <!--<string>MediaCallback</string>-->
63 <!--<string>MediaBuffering</string>--> 64 <!--<string>MediaBuffering</string>-->
diff --git a/linden/indra/newview/app_settings/settings.xml b/linden/indra/newview/app_settings/settings.xml
index 59c2982..2a508ee 100644
--- a/linden/indra/newview/app_settings/settings.xml
+++ b/linden/indra/newview/app_settings/settings.xml
@@ -7990,6 +7990,33 @@
7990 <key>Value</key> 7990 <key>Value</key>
7991 <real>3.0</real> 7991 <real>3.0</real>
7992 </map> 7992 </map>
7993 <key>MediaEnableFilter</key>
7994 <map>
7995 <key>Comment</key>
7996 <string>Enable media domain filtering</string>
7997 <key>Persist</key>
7998 <integer>1</integer>
7999 <key>Type</key>
8000 <string>Boolean</string>
8001 <key>Value</key>
8002 <integer>1</integer>
8003 </map>
8004 <key>MediaFilterRect</key>
8005 <map>
8006 <key>Comment</key>
8007 <string>Rectangle for Media Filter floater</string>
8008 <key>Persist</key>
8009 <integer>1</integer>
8010 <key>Type</key>
8011 <string>Rect</string>
8012 <key>Value</key>
8013 <array>
8014 <integer>0</integer>
8015 <integer>100</integer>
8016 <integer>100</integer>
8017 <integer>100</integer>
8018 </array>
8019 </map>
7993 <key>MediaOnAPrimUI</key> 8020 <key>MediaOnAPrimUI</key>
7994 <map> 8021 <map>
7995 <key>Comment</key> 8022 <key>Comment</key>
diff --git a/linden/indra/newview/lloverlaybar.cpp b/linden/indra/newview/lloverlaybar.cpp
index 4e1d03e..93b73c7 100644
--- a/linden/indra/newview/lloverlaybar.cpp
+++ b/linden/indra/newview/lloverlaybar.cpp
@@ -383,6 +383,23 @@ void LLOverlayBar::onClickStandUp(void*)
383} 383}
384 384
385//////////////////////////////////////////////////////////////////////////////// 385////////////////////////////////////////////////////////////////////////////////
386void LLOverlayBar::audioFilterPlay()
387{
388 if (gOverlayBar && gOverlayBar->mMusicState != PLAYING)
389 {
390 gOverlayBar->mMusicState = PLAYING;
391 }
392}
393
394void LLOverlayBar::audioFilterStop()
395{
396 if (gOverlayBar && gOverlayBar->mMusicState != STOPPED)
397 {
398 gOverlayBar->mMusicState = STOPPED;
399 }
400}
401
402////////////////////////////////////////////////////////////////////////////////
386// static media helpers 403// static media helpers
387// *TODO: Move this into an audio manager abstraction 404// *TODO: Move this into an audio manager abstraction
388//static 405//static
@@ -416,6 +433,7 @@ void LLOverlayBar::toggleMediaPlay(void*)
416 LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); 433 LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
417 if (parcel) 434 if (parcel)
418 { 435 {
436 LLViewerParcelMedia::sIsUserAction = true;
419 LLViewerParcelMedia::play(parcel); 437 LLViewerParcelMedia::play(parcel);
420 } 438 }
421 } 439 }
@@ -447,7 +465,8 @@ void LLOverlayBar::toggleMusicPlay(void*)
447 // stream is stopped, it doesn't return the right thing - commenting out for now. 465 // stream is stopped, it doesn't return the right thing - commenting out for now.
448 // if ( gAudioStream->isInternetStreamPlaying() == 0 ) 466 // if ( gAudioStream->isInternetStreamPlaying() == 0 )
449 { 467 {
450 gAudioStream->startInternetStream(parcel->getMusicURL()); 468 LLViewerParcelMedia::sIsUserAction = true;
469 LLViewerParcelMedia::playStreamingMusic(parcel);
451 } 470 }
452 } 471 }
453 } 472 }
diff --git a/linden/indra/newview/lloverlaybar.h b/linden/indra/newview/lloverlaybar.h
index 233f5c5..f776639 100644
--- a/linden/indra/newview/lloverlaybar.h
+++ b/linden/indra/newview/lloverlaybar.h
@@ -77,6 +77,10 @@ public:
77 static void onClickStandUp(void* data); 77 static void onClickStandUp(void* data);
78 static void onClickResetView(void* data); 78 static void onClickResetView(void* data);
79 79
80 // media filter
81 static void audioFilterPlay();
82 static void audioFilterStop();
83
80 //static media helper functions 84 //static media helper functions
81 static void toggleMediaPlay(void*); 85 static void toggleMediaPlay(void*);
82 static void toggleMusicPlay(void*); 86 static void toggleMusicPlay(void*);
diff --git a/linden/indra/newview/llstartup.cpp b/linden/indra/newview/llstartup.cpp
index 5a3a8ee..a74744b 100644
--- a/linden/indra/newview/llstartup.cpp
+++ b/linden/indra/newview/llstartup.cpp
@@ -2822,6 +2822,8 @@ bool idle_startup()
2822 gFloaterTeleportHistory->addEntry(regionp->getName(),(S16)agent_pos.mV[0],(S16)agent_pos.mV[1],(S16)agent_pos.mV[2],false); 2822 gFloaterTeleportHistory->addEntry(regionp->getName(),(S16)agent_pos.mV[0],(S16)agent_pos.mV[1],(S16)agent_pos.mV[2],false);
2823 } 2823 }
2824 2824
2825 LLViewerParcelMedia::loadDomainFilterList();
2826
2825 // Let the map know about the inventory. 2827 // Let the map know about the inventory.
2826 if(gFloaterWorldMap) 2828 if(gFloaterWorldMap)
2827 { 2829 {
diff --git a/linden/indra/newview/llviewercontrol.cpp b/linden/indra/newview/llviewercontrol.cpp
index 572f64a..0a23045 100644
--- a/linden/indra/newview/llviewercontrol.cpp
+++ b/linden/indra/newview/llviewercontrol.cpp
@@ -63,6 +63,7 @@
63#include "llworld.h" 63#include "llworld.h"
64#include "pipeline.h" 64#include "pipeline.h"
65#include "llviewerjoystick.h" 65#include "llviewerjoystick.h"
66#include "llviewerparcelmedia.h"
66#include "llviewerparcelmgr.h" 67#include "llviewerparcelmgr.h"
67#include "llparcel.h" 68#include "llparcel.h"
68#include "llnotify.h" 69#include "llnotify.h"
@@ -324,7 +325,7 @@ static bool handleAudioStreamMusicChanged(const LLSD& newvalue)
324 // otherwise music will briefly stop 325 // otherwise music will briefly stop
325 if ( !gAudioStream->isInternetStreamPlaying() ) 326 if ( !gAudioStream->isInternetStreamPlaying() )
326 { 327 {
327 gAudioStream->startInternetStream(LLViewerParcelMgr::getInstance()->getAgentParcel()->getMusicURL()); 328 LLViewerParcelMedia::playStreamingMusic(LLViewerParcelMgr::getInstance()->getAgentParcel());
328 } 329 }
329 } 330 }
330 } 331 }
diff --git a/linden/indra/newview/llviewermenu.cpp b/linden/indra/newview/llviewermenu.cpp
index cf3cec1..a22f704 100644
--- a/linden/indra/newview/llviewermenu.cpp
+++ b/linden/indra/newview/llviewermenu.cpp
@@ -234,6 +234,7 @@
234#include "hippolimits.h" 234#include "hippolimits.h"
235 235
236#include "llfloaterteleporthistory.h" 236#include "llfloaterteleporthistory.h"
237#include "slfloatermediafilter.h"
237 238
238using namespace LLVOAvatarDefines; 239using namespace LLVOAvatarDefines;
239void init_client_menu(LLMenuGL* menu); 240void init_client_menu(LLMenuGL* menu);
@@ -5996,6 +5997,10 @@ class LLShowFloater : public view_listener_t
5996 { 5997 {
5997 LLFloaterMute::toggleInstance(); 5998 LLFloaterMute::toggleInstance();
5998 } 5999 }
6000 else if (floater_name == "media filter")
6001 {
6002 SLFloaterMediaFilter::toggleInstance();
6003 }
5999 else if (floater_name == "camera controls") 6004 else if (floater_name == "camera controls")
6000 { 6005 {
6001 LLFloaterCamera::toggleInstance(); 6006 LLFloaterCamera::toggleInstance();
@@ -6161,6 +6166,10 @@ class LLFloaterVisible : public view_listener_t
6161 { 6166 {
6162 new_value = LLFloaterMute::instanceVisible(); 6167 new_value = LLFloaterMute::instanceVisible();
6163 } 6168 }
6169 else if (floater_name == "media filter")
6170 {
6171 new_value = SLFloaterMediaFilter::instanceVisible();
6172 }
6164 else if (floater_name == "camera controls") 6173 else if (floater_name == "camera controls")
6165 { 6174 {
6166 new_value = LLFloaterCamera::instanceVisible(); 6175 new_value = LLFloaterCamera::instanceVisible();
diff --git a/linden/indra/newview/llviewerparcelmedia.cpp b/linden/indra/newview/llviewerparcelmedia.cpp
index d4ebbd9..a5d97f2 100644
--- a/linden/indra/newview/llviewerparcelmedia.cpp
+++ b/linden/indra/newview/llviewerparcelmedia.cpp
@@ -33,6 +33,7 @@
33#include "llviewerprecompiledheaders.h" 33#include "llviewerprecompiledheaders.h"
34#include "llviewerparcelmedia.h" 34#include "llviewerparcelmedia.h"
35 35
36#include "kokuastreamingaudio.h"
36#include "llagent.h" 37#include "llagent.h"
37#include "llviewercontrol.h" 38#include "llviewercontrol.h"
38#include "llviewermedia.h" 39#include "llviewermedia.h"
@@ -46,17 +47,27 @@
46#include "llviewerwindow.h" 47#include "llviewerwindow.h"
47#include "llfirstuse.h" 48#include "llfirstuse.h"
48#include "llpluginclassmedia.h" 49#include "llpluginclassmedia.h"
50#include "llnotify.h"
51#include "llsdserialize.h"
49 52
53#include "lloverlaybar.h"
54#include "slfloatermediafilter.h"
55#include "llinventorymodel.h"
50// Static Variables 56// Static Variables
51 57
52S32 LLViewerParcelMedia::sMediaParcelLocalID = 0; 58S32 LLViewerParcelMedia::sMediaParcelLocalID = 0;
53LLUUID LLViewerParcelMedia::sMediaRegionID; 59LLUUID LLViewerParcelMedia::sMediaRegionID;
54viewer_media_t LLViewerParcelMedia::sMediaImpl; 60viewer_media_t LLViewerParcelMedia::sMediaImpl;
55 61bool LLViewerParcelMedia::sIsUserAction = false;
62bool LLViewerParcelMedia::sMediaFilterListLoaded = false;
63LLSD LLViewerParcelMedia::sMediaFilterList;
64std::set<std::string> LLViewerParcelMedia::sMediaQueries;
65std::set<std::string> LLViewerParcelMedia::sAllowedMedia;
66std::set<std::string> LLViewerParcelMedia::sDeniedMedia;
56 67
57// Local functions 68// Local functions
58bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel); 69bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel);
59 70void callback_media_alert(const LLSD& notification, const LLSD& response, LLParcel* parcel, U32 type, std::string domain);
60 71
61// static 72// static
62void LLViewerParcelMedia::initClass() 73void LLViewerParcelMedia::initClass()
@@ -175,7 +186,7 @@ void LLViewerParcelMedia::update(LLParcel* parcel)
175} 186}
176 187
177// static 188// static
178void LLViewerParcelMedia::play(LLParcel* parcel) 189void LLViewerParcelMedia::play(LLParcel* parcel, bool filter)
179{ 190{
180 lldebugs << "LLViewerParcelMedia::play" << llendl; 191 lldebugs << "LLViewerParcelMedia::play" << llendl;
181 192
@@ -185,7 +196,17 @@ void LLViewerParcelMedia::play(LLParcel* parcel)
185 return; 196 return;
186 197
187 std::string media_url = parcel->getMediaURL(); 198 std::string media_url = parcel->getMediaURL();
188 std::string media_current_url = parcel->getMediaCurrentURL(); 199 LLStringUtil::trim(media_url);
200
201 if (!media_url.empty() && gSavedSettings.getBOOL("MediaEnableFilter") && (filter || !allowedMedia(media_url)))
202 {
203 // If filtering is needed or in case media_url just changed
204 // to something we did not yet approve.
205 LLViewerParcelMediaAutoPlay::playStarted();
206 filterMedia(parcel, 0);
207 return;
208 }
209
189 std::string mime_type = parcel->getMediaType(); 210 std::string mime_type = parcel->getMediaType();
190 LLUUID placeholder_texture_id = parcel->getMediaID(); 211 LLUUID placeholder_texture_id = parcel->getMediaID();
191 U8 media_auto_scale = parcel->getMediaAutoScale(); 212 U8 media_auto_scale = parcel->getMediaAutoScale();
@@ -403,6 +424,8 @@ void LLViewerParcelMedia::processParcelMediaUpdate( LLMessageSystem *msg, void *
403 media_url = media_url_buffer; 424 media_url = media_url_buffer;
404 msg->getU8("DataBlock", "MediaAutoScale", media_auto_scale); 425 msg->getU8("DataBlock", "MediaAutoScale", media_auto_scale);
405 426
427 LL_DEBUGS("MediaFilter") << "New media texture id: " << media_id << LL_ENDL;
428
406 if (msg->has("DataBlockExtended")) // do we have the extended data? 429 if (msg->has("DataBlockExtended")) // do we have the extended data?
407 { 430 {
408 char media_type_buffer[257]; 431 char media_type_buffer[257];
@@ -438,6 +461,7 @@ void LLViewerParcelMedia::processParcelMediaUpdate( LLMessageSystem *msg, void *
438 461
439 play(parcel); 462 play(parcel);
440 } 463 }
464
441 } 465 }
442} 466}
443// Static 467// Static
@@ -586,3 +610,368 @@ void LLViewerParcelMediaNavigationObserver::onNavigateComplete( const EventType&
586 610
587} 611}
588*/ 612*/
613
614void LLViewerParcelMedia::playStreamingMusic(LLParcel* parcel, bool filter)
615{
616 std::string music_url = parcel->getMusicURL();
617 LLStringUtil::trim(music_url);
618 if (!music_url.empty() && gSavedSettings.getBOOL("MediaEnableFilter") && (filter || !allowedMedia(music_url)))
619 {
620 // If filtering is needed or in case music_url just changed
621 // to something we did not yet approve.
622 filterMedia(parcel, 1);
623 }
624 else if (gAudioStream)
625 {
626 LLStringUtil::trim(music_url);
627 gAudioStream->startInternetStream(music_url);
628 if (music_url.empty())
629 {
630 LLOverlayBar::audioFilterStop();
631 }
632 else
633 {
634 LLOverlayBar::audioFilterPlay();
635 }
636 }
637}
638
639void LLViewerParcelMedia::stopStreamingMusic()
640{
641 if (gAudioStream)
642 {
643 gAudioStream->stopInternetStream();
644 LLOverlayBar::audioFilterStop();
645 }
646}
647
648bool LLViewerParcelMedia::allowedMedia(std::string media_url)
649{
650 LLStringUtil::trim(media_url);
651 std::string domain = extractDomain(media_url);
652 if (sAllowedMedia.count(domain))
653 {
654 return true;
655 }
656 for (S32 i = 0; i < (S32)sMediaFilterList.size(); i++)
657 {
658 if (sMediaFilterList[i]["domain"].asString() == domain)
659 {
660 if (sMediaFilterList[i]["action"].asString() == "allow")
661 {
662 return true;
663 }
664 else
665 {
666 return false;
667 }
668 }
669 }
670 return false;
671}
672
673void LLViewerParcelMedia::filterMedia(LLParcel* parcel, U32 type)
674{
675 std::string media_action;
676 std::string media_url;
677 std::string domain;
678
679 if (parcel != LLViewerParcelMgr::getInstance()->getAgentParcel())
680 {
681 // The parcel just changed (may occur right out after a TP)
682 sIsUserAction = false;
683 return;
684 }
685
686 if (type == 0)
687 {
688 media_url = parcel->getMediaURL();
689 }
690 else
691 {
692 media_url = parcel->getMusicURL();
693 }
694 LLStringUtil::trim(media_url);
695
696 LL_DEBUGS("MediaFilter") << "Requested " << (type == 0 ? "media" : "music") << "-URL: " << media_url << LL_ENDL;
697
698 domain = extractDomain(media_url);
699
700 if (sMediaQueries.count(domain) > 0)
701 {
702 sIsUserAction = false;
703 return;
704 }
705
706 if (sIsUserAction)
707 {
708 // This was a user manual request to play this media, so give
709 // it another chance...
710 sIsUserAction = false;
711 if (sDeniedMedia.count(domain))
712 {
713 sDeniedMedia.erase(domain);
714 SLFloaterMediaFilter::setDirty();
715 }
716 }
717
718 if (!sMediaFilterListLoaded || sDeniedMedia.count(domain))
719 {
720 media_action = "ignore";
721 }
722 else if (sAllowedMedia.count(domain))
723 {
724 media_action = "allow";
725 }
726 else
727 {
728 for (S32 i = 0; i < (S32)sMediaFilterList.size(); i++)
729 {
730 if (sMediaFilterList[i]["domain"].asString() == domain)
731 {
732 media_action = sMediaFilterList[i]["action"].asString();
733 break;
734 }
735 }
736 }
737
738 if (media_action == "allow" || media_url.empty())
739 {
740 if (type == 0)
741 {
742 play(parcel, false);
743 }
744 else
745 {
746 playStreamingMusic(parcel, false);
747 }
748 }
749 else if (media_action == "deny")
750 {
751 LLSD args;
752 args["DOMAIN"] = domain;
753 LLNotifications::instance().add("MediaBlocked", args);
754 if (type == 1)
755 {
756 LLViewerParcelMedia::stopStreamingMusic();
757 }
758 // So to avoid other "blocked" messages later in the session
759 // for this url should it be requested again by a script.
760 sDeniedMedia.insert(domain);
761 }
762 else if (media_action == "ignore")
763 {
764 if (type == 1)
765 {
766 LLViewerParcelMedia::stopStreamingMusic();
767 }
768 }
769 else
770 {
771 sMediaQueries.insert(domain);
772 LLSD args;
773 args["DOMAIN"] = domain;
774 if (media_url.find('?') != std::string::npos)
775 {
776 args["WARNING"] = " (WARNING: this URL also contains parameter(s) that could potentially be used to correlate your avatar name with your IP)";
777 }
778 else
779 {
780 args["WARNING"] = "";
781 }
782 if (type == 0)
783 {
784 args["TYPE"] = "a media";
785 }
786 else
787 {
788 args["TYPE"] = "an audio";
789 }
790 LLNotifications::instance().add("MediaAlert", args, LLSD(), boost::bind(callback_media_alert, _1, _2, parcel, type, domain));
791 }
792}
793
794void callback_media_alert(const LLSD &notification, const LLSD &response, LLParcel* parcel, U32 type, std::string domain)
795{
796 S32 option = LLNotification::getSelectedOption(notification, response);
797
798 LLSD args;
799 args["DOMAIN"] = domain;
800
801 if (option == 0 || option == 3) // Allow or Whitelist
802 {
803 LLViewerParcelMedia::sAllowedMedia.insert(domain);
804 if (option == 3) // Whitelist
805 {
806 LLSD newmedia;
807 newmedia["domain"] = domain;
808 newmedia["action"] = "allow";
809 LLViewerParcelMedia::sMediaFilterList.append(newmedia);
810 LLViewerParcelMedia::saveDomainFilterList();
811 args["LISTED"] = "whitelisted";
812 LLNotifications::instance().add("MediaListed", args);
813 }
814 if (type == 0)
815 {
816 LLViewerParcelMedia::play(parcel, false);
817 }
818 else
819 {
820 LLViewerParcelMedia::playStreamingMusic(parcel, false);
821 }
822 }
823 else if (option == 1 || option == 2) // Deny or Blacklist
824 {
825 LLViewerParcelMedia::sDeniedMedia.insert(domain);
826 if (type == 1)
827 {
828 LLViewerParcelMedia::stopStreamingMusic();
829 }
830 if (option == 1) // Deny
831 {
832 LLNotifications::instance().add("MediaBlocked", args);
833 }
834 else // Blacklist
835 {
836 LLSD newmedia;
837 newmedia["domain"] = domain;
838 newmedia["action"] = "deny";
839 LLViewerParcelMedia::sMediaFilterList.append(newmedia);
840 LLViewerParcelMedia::saveDomainFilterList();
841 args["LISTED"] = "blacklisted";
842 LLNotifications::instance().add("MediaListed", args);
843 }
844 }
845
846 LLViewerParcelMedia::sMediaQueries.erase(domain);
847 SLFloaterMediaFilter::setDirty();
848}
849
850void LLViewerParcelMedia::saveDomainFilterList()
851{
852 std::string medialist_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "media_filter.xml");
853
854 llofstream medialistFile(medialist_filename);
855 LLSDSerialize::toPrettyXML(sMediaFilterList, medialistFile);
856 medialistFile.close();
857}
858
859bool LLViewerParcelMedia::loadDomainFilterList()
860{
861 sMediaFilterListLoaded = true;
862
863 std::string medialist_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "media_filter.xml");
864
865 if (!LLFile::isfile(medialist_filename))
866 {
867 LLSD emptyllsd;
868 llofstream medialistFile(medialist_filename);
869 LLSDSerialize::toPrettyXML(emptyllsd, medialistFile);
870 medialistFile.close();
871 }
872
873 if (LLFile::isfile(medialist_filename))
874 {
875 llifstream medialistFile(medialist_filename);
876 LLSDSerialize::fromXML(sMediaFilterList, medialistFile);
877 medialistFile.close();
878 SLFloaterMediaFilter::setDirty();
879 return true;
880 }
881 else
882 {
883 return false;
884 }
885}
886
887void LLViewerParcelMedia::clearDomainFilterList()
888{
889 sMediaFilterList.clear();
890 sAllowedMedia.clear();
891 sDeniedMedia.clear();
892 saveDomainFilterList();
893 LLNotifications::instance().add("MediaFiltersCleared");
894 SLFloaterMediaFilter::setDirty();
895}
896
897std::string LLViewerParcelMedia::extractDomain(std::string url)
898{
899 static std::string last_region = "@";
900
901 if (url.empty())
902 {
903 return url;
904 }
905
906 LLStringUtil::toLower(url);
907
908 size_t pos = url.find("//");
909
910 if (pos != std::string::npos)
911 {
912 size_t count = url.size() - pos + 2;
913 url = url.substr(pos + 2, count);
914 }
915
916 // Check that there is at least one slash in the URL and add a trailing
917 // one if not (for media/audio URLs such as http://mydomain.net)
918 if (url.find('/') == std::string::npos)
919 {
920 url += '/';
921 }
922
923 // If there's a user:password@ part, remove it
924 pos = url.find('@');
925 if (pos != std::string::npos && pos < url.find('/')) // if '@' is not before the first '/', then it's not a user:password
926 {
927 size_t count = url.size() - pos + 1;
928 url = url.substr(pos + 1, count);
929 }
930
931 if (url.find(gAgent.getRegion()->getHost().getHostName()) == 0 || url.find(last_region) == 0)
932 {
933 // This must be a scripted object rezzed in the region:
934 // extend the concept of "domain" to encompass the
935 // scripted object server id and avoid blocking all other
936 // objects at once in this region...
937
938 // Get rid of any port number
939 pos = url.find('/'); // We earlier made sure that there's one
940 url = gAgent.getRegion()->getHost().getHostName() + url.substr(pos);
941
942 pos = url.find('?');
943 if (pos != std::string::npos)
944 {
945 // Get rid of any parameter
946 url = url.substr(0, pos);
947 }
948
949 pos = url.rfind('/');
950 if (pos != std::string::npos)
951 {
952 // Get rid of the filename, if any, keeping only the server + path
953 url = url.substr(0, pos);
954 }
955 }
956 else
957 {
958 pos = url.find(':');
959 if (pos != std::string::npos && pos < url.find('/'))
960 {
961 // Keep anything before the port number and strip the rest off
962 url = url.substr(0, pos);
963 }
964 else
965 {
966 pos = url.find('/'); // We earlier made sure that there's one
967 url = url.substr(0, pos);
968 }
969 }
970
971
972 // Remember this region, so to cope with requests occuring just after a
973 // TP out of it.
974 last_region = gAgent.getRegion()->getHost().getHostName();
975
976 return url;
977}
diff --git a/linden/indra/newview/llviewerparcelmedia.h b/linden/indra/newview/llviewerparcelmedia.h
index 0f1e85c..7531a0f 100644
--- a/linden/indra/newview/llviewerparcelmedia.h
+++ b/linden/indra/newview/llviewerparcelmedia.h
@@ -35,6 +35,9 @@
35 35
36#include "llviewermedia.h" 36#include "llviewermedia.h"
37 37
38// For use by other patches so they know that media filtering is implemented.
39#define MEDIA_FILTERING 1
40
38class LLMessageSystem; 41class LLMessageSystem;
39class LLParcel; 42class LLParcel;
40class LLViewerParcelMediaNavigationObserver; 43class LLViewerParcelMediaNavigationObserver;
@@ -54,8 +57,20 @@ class LLViewerParcelMedia : public LLViewerMediaObserver
54 // called when the agent's parcel has a new URL, or the agent has 57 // called when the agent's parcel has a new URL, or the agent has
55 // walked on to a new parcel with media 58 // walked on to a new parcel with media
56 59
57 static void play(LLParcel* parcel); 60 static void play(LLParcel* parcel, bool filter = true);
58 // user clicked play button in media transport controls 61 // user clicked play button in media transport controls
62 static void playStreamingMusic(LLParcel* parcel, bool filter = true);
63 // play the parcel music stream
64 static void stopStreamingMusic();
65 // stop the parcel music stream
66
67 static void filterMedia(LLParcel* parcel, U32 type); // type: 0 = media, 1 = streaming music
68 static bool allowedMedia(std::string media_url);
69
70 static bool loadDomainFilterList();
71 static void saveDomainFilterList();
72 static void clearDomainFilterList();
73 static std::string extractDomain(std::string url);
59 74
60 static void stop(); 75 static void stop();
61 // user clicked stop button in media transport controls 76 // user clicked stop button in media transport controls
@@ -85,6 +100,13 @@ class LLViewerParcelMedia : public LLViewerMediaObserver
85 static LLUUID sMediaRegionID; 100 static LLUUID sMediaRegionID;
86 // HACK: this will change with Media on a Prim 101 // HACK: this will change with Media on a Prim
87 static viewer_media_t sMediaImpl; 102 static viewer_media_t sMediaImpl;
103
104 static bool sIsUserAction;
105 static bool sMediaFilterListLoaded;
106 static LLSD sMediaFilterList;
107 static std::set<std::string> sMediaQueries;
108 static std::set<std::string> sAllowedMedia;
109 static std::set<std::string> sDeniedMedia;
88}; 110};
89 111
90 112
diff --git a/linden/indra/newview/llviewerparcelmgr.cpp b/linden/indra/newview/llviewerparcelmgr.cpp
index 630da54..9db65c6 100644
--- a/linden/indra/newview/llviewerparcelmgr.cpp
+++ b/linden/indra/newview/llviewerparcelmgr.cpp
@@ -85,7 +85,7 @@ LLPointer<LLViewerImage> sBlockedImage;
85LLPointer<LLViewerImage> sPassImage; 85LLPointer<LLViewerImage> sPassImage;
86 86
87// Local functions 87// Local functions
88void optionally_start_music(const std::string& music_url); 88void optionally_start_music(LLParcel* parcel);
89void callback_start_music(S32 option, void* data); 89void callback_start_music(S32 option, void* data);
90void optionally_prepare_video(const LLParcel *parcelp); 90void optionally_prepare_video(const LLParcel *parcelp);
91void callback_prepare_video(S32 option, void* data); 91void callback_prepare_video(S32 option, void* data);
@@ -1697,7 +1697,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
1697 { 1697 {
1698 if (music_url.substr(0,7) == "http://") 1698 if (music_url.substr(0,7) == "http://")
1699 { 1699 {
1700 optionally_start_music(music_url); 1700 optionally_start_music(parcel);
1701 } 1701 }
1702 } 1702 }
1703 else if (!gAudioStream->getInternetStreamURL().empty()) 1703 else if (!gAudioStream->getInternetStreamURL().empty())
@@ -1719,18 +1719,18 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
1719 }; 1719 };
1720} 1720}
1721 1721
1722void optionally_start_music(const std::string& music_url) 1722void optionally_start_music(LLParcel* parcel)
1723{ 1723{
1724 if (gSavedSettings.getBOOL("AudioStreamingMusic")) 1724 if (gSavedSettings.getBOOL("AudioStreamingMusic"))
1725 { 1725 {
1726 // Make the user click the start button on the overlay bar. JC 1726 // Make the user click the start button on the overlay bar. JC
1727 // llinfos << "Starting parcel music " << music_url << llendl; 1727 // llinfos << "Starting parcel music " << parcel->getMusicURL() << llendl;
1728 1728
1729 // now only play music when you enter a new parcel if the control is in PLAY state 1729 // now only play music when you enter a new parcel if the control is in PLAY state
1730 // changed as part of SL-4878 1730 // changed as part of SL-4878
1731 if ( gOverlayBar && gOverlayBar->musicPlaying()) 1731 if (gOverlayBar && gOverlayBar->musicPlaying())
1732 { 1732 {
1733 gAudioStream->startInternetStream(music_url); 1733 LLViewerParcelMedia::playStreamingMusic(parcel);
1734 } 1734 }
1735 } 1735 }
1736} 1736}
diff --git a/linden/indra/newview/skins/default/xui/en-us/floater_media_filter.xml b/linden/indra/newview/skins/default/xui/en-us/floater_media_filter.xml
new file mode 100644
index 0000000..9b7355c
--- /dev/null
+++ b/linden/indra/newview/skins/default/xui/en-us/floater_media_filter.xml
@@ -0,0 +1,61 @@
1<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
2<floater name="floatermediafilter" title="Media Filter" rect_control="MediaFilterRect"
3 can_close="true" can_drag_on_left="false" can_minimize="true" can_resize="true"
4 height="350" width="600" min_height="350" min_width="600">
5 <text name="info1" font="SansSerif" mouse_opaque="true" halign="center"
6 bottom_delta="-45" left="20" height="20" width="560" follows="left|right|top">
7 Domains in bold are in the persistent list (i.e. they are whitelisted or blacklisted).
8 </text>
9 <text name="info2" font="SansSerif" mouse_opaque="true" halign="center"
10 bottom_delta="-20" left="20" height="20" width="560" follows="left|right|top">
11 Domains in italics are in the session list (i.e. they are temporarily allowed or denied).
12 </text>
13
14 <scroll_list name="whitelist_list" follows="top|bottom|left"
15 background_visible="true" mouse_opaque="true"
16 multi_select="false" column_padding="5" draw_border="true" draw_heading="true"
17 bottom_delta="-205" left="15" height="200" width="280">
18 <column name="whitelist_col" label="Allowed domains/objects" dynamicwidth="true" />
19 </scroll_list>
20
21 <scroll_list name="blacklist_list" follows="top|bottom|right"
22 background_visible="true" mouse_opaque="true"
23 multi_select="false" column_padding="5" draw_border="true" draw_heading="true"
24 bottom_delta="0" right="-15" height="200" width="280">
25 <column name="blacklist_col" label="Blocked domains/objects" dynamicwidth="true" />
26 </scroll_list>
27
28 <button name="add_whitelist" font="SansSerif" label="Add..." halign="center"
29 enabled="true" mouse_opaque="true" follows="bottom|left"
30 bottom_delta="-25" left="30" height="20" width="80" />
31
32 <button name="remove_whitelist" font="SansSerif" label="Remove" halign="center"
33 enabled="true" mouse_opaque="true" follows="bottom|left"
34 bottom_delta="0" left_delta="100" height="20" width="80" />
35
36 <button name="clear_lists" font="SansSerif" label="Clear lists" halign="center"
37 enabled="true" mouse_opaque="true" follows="bottom|left|right"
38 bottom_delta="0" left_delta="110" height="20" width="120" />
39
40 <button name="add_blacklist" font="SansSerif" label="Add..." halign="center"
41 enabled="true" mouse_opaque="true" follows="bottom|right"
42 bottom_delta="0" right="-130" height="20" width="80" />
43
44 <button name="remove_blacklist" font="SansSerif" label="Remove" halign="center"
45 enabled="true" mouse_opaque="true" follows="bottom|right"
46 bottom_delta="0" right="-30" height="20" width="80" />
47
48 <text name="add_text" font="SansSerif" mouse_opaque="true" enabled="true"
49 bottom_delta="-25" left="20" height="20" width="500" follows="left|right|bottom">
50 New domain:
51 </text>
52
53 <line_editor name="input_domain" max_length="255" font="SansSerif" enabled="false"
54 select_all_on_focus_received="true" select_on_focus="true"
55 bevel_style="in" border_style="line" border_thickness="1"
56 bottom_delta="-20" right="-100" height="20" left="15" follows="left|bottom|right"/>
57
58 <button name="commit_domain" font="SansSerif" label="Add" halign="center" enabled="false"
59 mouse_opaque="true" follows="bottom|right"
60 bottom_delta="0" right="-15" height="20" width="80"/>
61</floater>
diff --git a/linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml b/linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml
index 4bde0f0..5fbf337 100644
--- a/linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml
+++ b/linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml
@@ -277,6 +277,11 @@
277 <on_click function="ShowAgentGroups" 277 <on_click function="ShowAgentGroups"
278 userdata="agent" /> 278 userdata="agent" />
279 </menu_item_call> 279 </menu_item_call>
280 <menu_item_check bottom="-192" enabled="true" height="19" label="Media Filter" left="0"
281 mouse_opaque="true" name="Media Filter" width="211">
282 <on_click function="ShowFloater" userdata="media filter" />
283 <on_check function="FloaterVisible" userdata="media filter" />
284 </menu_item_check>
280 <menu_item_separator /> 285 <menu_item_separator />
281 <menu_item_call name="Preferences..." label="Preferences..." 286 <menu_item_call name="Preferences..." label="Preferences..."
282 shortcut="control|P"> 287 shortcut="control|P">
diff --git a/linden/indra/newview/skins/default/xui/en-us/notifications.xml b/linden/indra/newview/skins/default/xui/en-us/notifications.xml
index 47d3dbb..27f5529 100644
--- a/linden/indra/newview/skins/default/xui/en-us/notifications.xml
+++ b/linden/indra/newview/skins/default/xui/en-us/notifications.xml
@@ -7320,6 +7320,56 @@ The Second Life Terms of Service do not allow you to opt out. By logging in to S
7320 notext="Cancel"/> 7320 notext="Cancel"/>
7321</notification> 7321</notification>
7322 7322
7323 <notification
7324 icon="alert.tga"
7325 name="MediaAlert"
7326 type="alert">
7327The owner of this parcel has requested [TYPE] URL pertaining to the following domain or scripted object to be loaded by your viewer[WARNING]:
7328
7329[DOMAIN]
7330
7331"Allow" and "Deny" apply only for this session, while "Blacklist" and "Whitelist" apply forever to the above domain or scripted object.
7332 <form name="form">
7333 <button
7334 index="0"
7335 name="Allow"
7336 text="Allow"/>
7337 <button
7338 index="1"
7339 name="Deny"
7340 text="Deny"/>
7341 <button
7342 index="2"
7343 name="Blacklist"
7344 text="Blacklist"/>
7345 <button
7346 index="3"
7347 name="Whitelist"
7348 text="Whitelist"/>
7349 </form>
7350 </notification>
7351
7352 <notification
7353 icon="alert.tga"
7354 name="MediaListed"
7355 type="alert">
7356Media/audio URLs for [DOMAIN] now [LISTED]
7357 </notification>
7358
7359 <notification
7360 icon="notifytip.tga"
7361 name="MediaBlocked"
7362 type="notifytip">
7363Media/audio URL blocked for [DOMAIN]
7364 </notification>
7365
7366 <notification
7367 icon="alertmodal.tga"
7368 name="MediaFiltersCleared"
7369 type="alertmodal">
7370The media filters have been cleared
7371 </notification>
7372
7323<!--End Imprudence notifications--> 7373<!--End Imprudence notifications-->
7324 <!-- [KITTY VIEWER] --> 7374 <!-- [KITTY VIEWER] -->
7325 <notification 7375 <notification
diff --git a/linden/indra/newview/slfloatermediafilter.cpp b/linden/indra/newview/slfloatermediafilter.cpp
new file mode 100644
index 0000000..c47ed26
--- /dev/null
+++ b/linden/indra/newview/slfloatermediafilter.cpp
@@ -0,0 +1,350 @@
1/**
2 * @file slfloatermediafilter.cpp
3 * @brief The SLFloaterMediaFilter class definitions
4 *
5 * $LicenseInfo:firstyear=2011&license=viewergpl$
6 *
7 * Copyright (c) 2011, Sione Lomu
8 * with debugging and improvements by Henri Beauchamp
9 *
10 * Second Life Viewer Source Code
11 * The source code in this file ("Source Code") is provided by Linden Lab
12 * to you under the terms of the GNU General Public License, version 2.0
13 * ("GPL"), unless you have obtained a separate licensing agreement
14 * ("Other License"), formally executed by you and Linden Lab. Terms of
15 * the GPL can be found in doc/GPL-license.txt in this distribution, or
16 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
17 *
18 * There are special exceptions to the terms and conditions of the GPL as
19 * it is applied to this Source Code. View the full text of the exception
20 * in the file doc/FLOSS-exception.txt in this software distribution, or
21 * online at
22 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
23 *
24 * By copying, modifying or distributing this software, you acknowledge
25 * that you have read and understood your obligations described above,
26 * and agree to abide by those obligations.
27 *
28 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
29 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
30 * COMPLETENESS OR PERFORMANCE.
31 * $/LicenseInfo$
32 */
33
34#include "llviewerprecompiledheaders.h"
35
36#include "lllineeditor.h"
37#include "llscrolllistctrl.h"
38#include "lluictrlfactory.h"
39
40#include "slfloatermediafilter.h"
41#include "llviewercontrol.h"
42#include "llviewerparcelmedia.h"
43
44SLFloaterMediaFilter* SLFloaterMediaFilter::sInstance = NULL;
45bool SLFloaterMediaFilter::sIsWhitelist = false;
46
47SLFloaterMediaFilter::SLFloaterMediaFilter() : LLFloater(std::string("media filter")), mIsDirty(false)
48{
49 LLUICtrlFactory::getInstance()->buildFloater(this, "floater_media_filter.xml");
50}
51
52SLFloaterMediaFilter::~SLFloaterMediaFilter()
53{
54 sInstance = NULL;
55}
56
57BOOL SLFloaterMediaFilter::postBuild()
58{
59 mWhitelistSLC = getChild<LLScrollListCtrl>("whitelist_list");
60 mBlacklistSLC = getChild<LLScrollListCtrl>("blacklist_list");
61
62 if (mWhitelistSLC && mBlacklistSLC)
63 {
64 childSetAction("clear_lists", onClearLists, this);
65 childSetAction("add_whitelist", onWhitelistAdd, this);
66 childSetAction("remove_whitelist", onWhitelistRemove, this);
67 childSetAction("add_blacklist", onBlacklistAdd, this);
68 childSetAction("remove_blacklist", onBlacklistRemove, this);
69 childSetAction("commit_domain", onCommitDomain, this);
70 childSetUserData("whitelist_list", this);
71 childSetUserData("blacklist_list", this);
72 mIsDirty = true;
73 }
74
75 return TRUE;
76}
77
78void SLFloaterMediaFilter::draw()
79{
80 if (mIsDirty && mWhitelistSLC && mBlacklistSLC)
81 {
82 S32 whitescrollpos = mWhitelistSLC->getScrollPos();
83 S32 blackscrollpos = mBlacklistSLC->getScrollPos();
84 mWhitelistSLC->deleteAllItems();
85 mBlacklistSLC->deleteAllItems();
86 std::set<std::string> listed;
87 std::string domain;
88 std::string action;
89 LLSD element;
90 element["columns"][0]["font"] = "SANSSERIF";
91 element["columns"][0]["font-style"] = "BOLD";
92 for (S32 i = 0; i < (S32)LLViewerParcelMedia::sMediaFilterList.size(); i++)
93 {
94 domain = LLViewerParcelMedia::sMediaFilterList[i]["domain"].asString();
95 action = LLViewerParcelMedia::sMediaFilterList[i]["action"].asString();
96 if (!domain.empty() && action == "allow")
97 {
98 element["columns"][0]["column"] = "whitelist_col";
99 element["columns"][0]["value"] = domain;
100 //element["columns"][0]["color"] = LLColor4::green3.getValue();
101 mWhitelistSLC->addElement(element, ADD_BOTTOM);
102 listed.insert(domain);
103 }
104 else if (!domain.empty() && action == "deny")
105 {
106 element["columns"][0]["column"] = "blacklist_col";
107 element["columns"][0]["value"] = domain;
108 //element["columns"][0]["color"] = LLColor4::red2.getValue();
109 mBlacklistSLC->addElement(element, ADD_BOTTOM);
110 listed.insert(domain);
111 }
112 else
113 {
114 LL_WARNS("MediaFilter") << "Bad media filter list: removing corrupted entry for \"" << domain << "\"" << LL_ENDL;
115 LLViewerParcelMedia::sMediaFilterList.erase(i--);
116 }
117 }
118 std::set<std::string>::iterator it;
119 element["columns"][0]["font"] = "SANSSERIF";
120 element["columns"][0]["font-style"] = "ITALIC";
121 //element["columns"][0]["color"] = LLColor4::green3.getValue();
122 element["columns"][0]["column"] = "whitelist_col";
123 for (it = LLViewerParcelMedia::sAllowedMedia.begin(); it != LLViewerParcelMedia::sAllowedMedia.end(); it++)
124 {
125 domain = *it;
126 if (listed.count(domain) == 0)
127 {
128 element["columns"][0]["value"] = domain;
129 mWhitelistSLC->addElement(element, ADD_BOTTOM);
130 }
131 }
132 element["columns"][0]["column"] = "blacklist_col";
133 for (it = LLViewerParcelMedia::sDeniedMedia.begin(); it != LLViewerParcelMedia::sDeniedMedia.end(); it++)
134 {
135 domain = *it;
136 if (listed.count(domain) == 0)
137 {
138 element["columns"][0]["value"] = domain;
139 mBlacklistSLC->addElement(element, ADD_BOTTOM);
140 }
141 }
142 mWhitelistSLC->setScrollPos(whitescrollpos);
143 mBlacklistSLC->setScrollPos(blackscrollpos);
144
145 if (!gSavedSettings.getBOOL("MediaEnableFilter"))
146 {
147 childDisable("clear_lists");
148 childDisable("blacklist_list");
149 childDisable("whitelist_list");
150 childDisable("remove_whitelist");
151 childDisable("add_whitelist");
152 childDisable("remove_blacklist");
153 childDisable("add_blacklist");
154 childDisable("input_domain");
155 childDisable("commit_domain");
156 childSetText("add_text", std::string("****** WARNING: media filtering is currently DISABLED ******"));
157 }
158
159 mIsDirty = false;
160 }
161
162 LLFloater::draw();
163}
164
165void SLFloaterMediaFilter::setDirty()
166{
167 if (sInstance)
168 {
169 sInstance->mIsDirty = true;
170 sInstance->draw();
171 }
172}
173
174BOOL SLFloaterMediaFilter::instanceVisible()
175{
176 if (sInstance)
177 {
178 return sInstance->getVisible();
179 }
180 else
181 {
182 return FALSE;
183 }
184}
185
186void SLFloaterMediaFilter::toggleInstance()
187{
188 if (sInstance)
189 {
190 if (sInstance->getVisible())
191 {
192 sInstance->destroy();
193 }
194 else
195 {
196 sInstance->open();
197 }
198 }
199 else
200 {
201 sInstance = new SLFloaterMediaFilter();
202 sInstance->open();
203 }
204}
205
206void SLFloaterMediaFilter::onClearLists(void* data)
207{
208 LLViewerParcelMedia::clearDomainFilterList();
209}
210
211void SLFloaterMediaFilter::onWhitelistAdd(void* data)
212{
213 if (!sInstance)
214 {
215 return;
216 }
217 sInstance->childDisable("clear_lists");
218 sInstance->childDisable("blacklist_list");
219 sInstance->childDisable("whitelist_list");
220 sInstance->childDisable("remove_whitelist");
221 sInstance->childDisable("add_whitelist");
222 sInstance->childDisable("remove_blacklist");
223 sInstance->childDisable("add_blacklist");
224 sInstance->childEnable("input_domain");
225 sInstance->childEnable("commit_domain");
226 sInstance->childSetText("add_text", std::string("Enter the domain/url to add to the white list:"));
227 sIsWhitelist = true;
228}
229
230void SLFloaterMediaFilter::onWhitelistRemove(void* data)
231{
232 if (!sInstance)
233 {
234 return;
235 }
236 LLScrollListItem* selected = sInstance->mWhitelistSLC->getFirstSelected();
237
238 if (selected)
239 {
240 std::string domain = sInstance->mWhitelistSLC->getSelectedItemLabel();
241 LLViewerParcelMedia::sAllowedMedia.erase(domain);
242
243 for (S32 i = 0; i < (S32)LLViewerParcelMedia::sMediaFilterList.size(); i++)
244 {
245 if (LLViewerParcelMedia::sMediaFilterList[i]["domain"].asString() == domain)
246 {
247 LLViewerParcelMedia::sMediaFilterList.erase(i);
248 LLViewerParcelMedia::saveDomainFilterList();
249 break;
250 }
251 }
252
253 setDirty();
254 }
255}
256
257void SLFloaterMediaFilter::onBlacklistAdd(void* data)
258{
259 if (!sInstance)
260 {
261 return;
262 }
263 sInstance->childDisable("clear_lists");
264 sInstance->childDisable("blacklist_list");
265 sInstance->childDisable("whitelist_list");
266 sInstance->childDisable("remove_whitelist");
267 sInstance->childDisable("add_whitelist");
268 sInstance->childDisable("remove_blacklist");
269 sInstance->childDisable("add_blacklist");
270 sInstance->childEnable("input_domain");
271 sInstance->childEnable("commit_domain");
272 sInstance->childSetText("add_text", std::string("Enter the domain/url to add to the black list:"));
273 sIsWhitelist = false;
274}
275
276void SLFloaterMediaFilter::onBlacklistRemove(void* data)
277{
278 if (!sInstance)
279 {
280 return;
281 }
282 LLScrollListItem* selected = sInstance->mBlacklistSLC->getFirstSelected();
283
284 if (selected)
285 {
286 std::string domain = sInstance->mBlacklistSLC->getSelectedItemLabel();
287 LLViewerParcelMedia::sDeniedMedia.erase(domain);
288
289 for (S32 i = 0; i < (S32)LLViewerParcelMedia::sMediaFilterList.size(); i++)
290 {
291 if (LLViewerParcelMedia::sMediaFilterList[i]["domain"].asString() == domain)
292 {
293 LLViewerParcelMedia::sMediaFilterList.erase(i);
294 LLViewerParcelMedia::saveDomainFilterList();
295 break;
296 }
297 }
298
299 setDirty();
300 }
301}
302
303void SLFloaterMediaFilter::onCommitDomain(void* data)
304{
305 if (!sInstance)
306 {
307 return;
308 }
309 std::string domain = sInstance->childGetText("input_domain");
310 domain = LLViewerParcelMedia::extractDomain(domain);
311
312 if (!domain.empty())
313 {
314 LLViewerParcelMedia::sDeniedMedia.erase(domain);
315 LLViewerParcelMedia::sAllowedMedia.erase(domain);
316 for (S32 i = 0; i < (S32)LLViewerParcelMedia::sMediaFilterList.size(); i++)
317 {
318 if (LLViewerParcelMedia::sMediaFilterList[i]["domain"].asString() == domain)
319 {
320 LLViewerParcelMedia::sMediaFilterList.erase(i);
321 break;
322 }
323 }
324 LLSD newmedia;
325 newmedia["domain"] = domain;
326 if (sIsWhitelist)
327 {
328 newmedia["action"] = "allow";
329 }
330 else
331 {
332 newmedia["action"] = "deny";
333 }
334 LLViewerParcelMedia::sMediaFilterList.append(newmedia);
335 LLViewerParcelMedia::saveDomainFilterList();
336 }
337
338 sInstance->childEnable("clear_lists");
339 sInstance->childEnable("blacklist_list");
340 sInstance->childEnable("whitelist_list");
341 sInstance->childEnable("remove_whitelist");
342 sInstance->childEnable("add_whitelist");
343 sInstance->childEnable("remove_blacklist");
344 sInstance->childEnable("add_blacklist");
345 sInstance->childDisable("input_domain");
346 sInstance->childDisable("commit_domain");
347 sInstance->childSetText("add_text", std::string("New domain:"));
348 sInstance->childSetText("input_domain", std::string(""));
349 setDirty();
350}
diff --git a/linden/indra/newview/slfloatermediafilter.h b/linden/indra/newview/slfloatermediafilter.h
new file mode 100644
index 0000000..0f900be
--- /dev/null
+++ b/linden/indra/newview/slfloatermediafilter.h
@@ -0,0 +1,70 @@
1/**
2 * @file slfloatermediafilter.h
3 * @brief The SLFloaterMediaFilter class declaration
4 *
5 * $LicenseInfo:firstyear=2011&license=viewergpl$
6 *
7 * Copyright (c) 2011, Sione Lomu
8 * with debugging and improvements by Henri Beauchamp
9 *
10 * Second Life Viewer Source Code
11 * The source code in this file ("Source Code") is provided by Linden Lab
12 * to you under the terms of the GNU General Public License, version 2.0
13 * ("GPL"), unless you have obtained a separate licensing agreement
14 * ("Other License"), formally executed by you and Linden Lab. Terms of
15 * the GPL can be found in doc/GPL-license.txt in this distribution, or
16 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
17 *
18 * There are special exceptions to the terms and conditions of the GPL as
19 * it is applied to this Source Code. View the full text of the exception
20 * in the file doc/FLOSS-exception.txt in this software distribution, or
21 * online at
22 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
23 *
24 * By copying, modifying or distributing this software, you acknowledge
25 * that you have read and understood your obligations described above,
26 * and agree to abide by those obligations.
27 *
28 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
29 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
30 * COMPLETENESS OR PERFORMANCE.
31 * $/LicenseInfo$
32 */
33
34#ifndef LL_SLFLOATERMEDIAFILTER_H
35#define LL_SLFLOATERMEDIAFILTER_H
36
37#include "llfloater.h"
38
39class LLScrollListCtrl;
40class LLButton;
41
42class SLFloaterMediaFilter : public LLFloater
43{
44public:
45 SLFloaterMediaFilter();
46 BOOL postBuild();
47 virtual void draw();
48 virtual ~SLFloaterMediaFilter();
49
50 static void setDirty();
51 static BOOL instanceVisible();
52 static void toggleInstance();
53
54 static void onClearLists(void*);
55 static void onWhitelistAdd(void*);
56 static void onWhitelistRemove(void*);
57 static void onBlacklistAdd(void*);
58 static void onBlacklistRemove(void*);
59 static void onCommitDomain(void*);
60
61private:
62 static bool sIsWhitelist;
63 LLScrollListCtrl* mWhitelistSLC;
64 LLScrollListCtrl* mBlacklistSLC;
65 bool mIsDirty;
66
67 static SLFloaterMediaFilter* sInstance;
68
69};
70#endif