diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/newview/CMakeLists.txt | 2 | ||||
-rw-r--r-- | linden/indra/newview/app_settings/logcontrol.xml | 1 | ||||
-rw-r--r-- | linden/indra/newview/app_settings/settings.xml | 27 | ||||
-rw-r--r-- | linden/indra/newview/lloverlaybar.cpp | 21 | ||||
-rw-r--r-- | linden/indra/newview/lloverlaybar.h | 4 | ||||
-rw-r--r-- | linden/indra/newview/llstartup.cpp | 2 | ||||
-rw-r--r-- | linden/indra/newview/llviewercontrol.cpp | 3 | ||||
-rw-r--r-- | linden/indra/newview/llviewermenu.cpp | 9 | ||||
-rw-r--r-- | linden/indra/newview/llviewerparcelmedia.cpp | 397 | ||||
-rw-r--r-- | linden/indra/newview/llviewerparcelmedia.h | 24 | ||||
-rw-r--r-- | linden/indra/newview/llviewerparcelmgr.cpp | 12 | ||||
-rw-r--r-- | linden/indra/newview/skins/default/xui/en-us/floater_media_filter.xml | 61 | ||||
-rw-r--r-- | linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml | 5 | ||||
-rw-r--r-- | linden/indra/newview/skins/default/xui/en-us/notifications.xml | 50 | ||||
-rw-r--r-- | linden/indra/newview/slfloatermediafilter.cpp | 350 | ||||
-rw-r--r-- | linden/indra/newview/slfloatermediafilter.h | 70 |
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 | //////////////////////////////////////////////////////////////////////////////// |
386 | void LLOverlayBar::audioFilterPlay() | ||
387 | { | ||
388 | if (gOverlayBar && gOverlayBar->mMusicState != PLAYING) | ||
389 | { | ||
390 | gOverlayBar->mMusicState = PLAYING; | ||
391 | } | ||
392 | } | ||
393 | |||
394 | void 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 | ||
238 | using namespace LLVOAvatarDefines; | 239 | using namespace LLVOAvatarDefines; |
239 | void init_client_menu(LLMenuGL* menu); | 240 | void 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 | ||
52 | S32 LLViewerParcelMedia::sMediaParcelLocalID = 0; | 58 | S32 LLViewerParcelMedia::sMediaParcelLocalID = 0; |
53 | LLUUID LLViewerParcelMedia::sMediaRegionID; | 59 | LLUUID LLViewerParcelMedia::sMediaRegionID; |
54 | viewer_media_t LLViewerParcelMedia::sMediaImpl; | 60 | viewer_media_t LLViewerParcelMedia::sMediaImpl; |
55 | 61 | bool LLViewerParcelMedia::sIsUserAction = false; | |
62 | bool LLViewerParcelMedia::sMediaFilterListLoaded = false; | ||
63 | LLSD LLViewerParcelMedia::sMediaFilterList; | ||
64 | std::set<std::string> LLViewerParcelMedia::sMediaQueries; | ||
65 | std::set<std::string> LLViewerParcelMedia::sAllowedMedia; | ||
66 | std::set<std::string> LLViewerParcelMedia::sDeniedMedia; | ||
56 | 67 | ||
57 | // Local functions | 68 | // Local functions |
58 | bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel); | 69 | bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel); |
59 | 70 | void callback_media_alert(const LLSD& notification, const LLSD& response, LLParcel* parcel, U32 type, std::string domain); | |
60 | 71 | ||
61 | // static | 72 | // static |
62 | void LLViewerParcelMedia::initClass() | 73 | void LLViewerParcelMedia::initClass() |
@@ -175,7 +186,7 @@ void LLViewerParcelMedia::update(LLParcel* parcel) | |||
175 | } | 186 | } |
176 | 187 | ||
177 | // static | 188 | // static |
178 | void LLViewerParcelMedia::play(LLParcel* parcel) | 189 | void 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 | |||
614 | void 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 | |||
639 | void LLViewerParcelMedia::stopStreamingMusic() | ||
640 | { | ||
641 | if (gAudioStream) | ||
642 | { | ||
643 | gAudioStream->stopInternetStream(); | ||
644 | LLOverlayBar::audioFilterStop(); | ||
645 | } | ||
646 | } | ||
647 | |||
648 | bool 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 | |||
673 | void 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 | |||
794 | void callback_media_alert(const LLSD ¬ification, 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 | |||
850 | void 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 | |||
859 | bool 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 | |||
887 | void LLViewerParcelMedia::clearDomainFilterList() | ||
888 | { | ||
889 | sMediaFilterList.clear(); | ||
890 | sAllowedMedia.clear(); | ||
891 | sDeniedMedia.clear(); | ||
892 | saveDomainFilterList(); | ||
893 | LLNotifications::instance().add("MediaFiltersCleared"); | ||
894 | SLFloaterMediaFilter::setDirty(); | ||
895 | } | ||
896 | |||
897 | std::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 | |||
38 | class LLMessageSystem; | 41 | class LLMessageSystem; |
39 | class LLParcel; | 42 | class LLParcel; |
40 | class LLViewerParcelMediaNavigationObserver; | 43 | class 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; | |||
85 | LLPointer<LLViewerImage> sPassImage; | 85 | LLPointer<LLViewerImage> sPassImage; |
86 | 86 | ||
87 | // Local functions | 87 | // Local functions |
88 | void optionally_start_music(const std::string& music_url); | 88 | void optionally_start_music(LLParcel* parcel); |
89 | void callback_start_music(S32 option, void* data); | 89 | void callback_start_music(S32 option, void* data); |
90 | void optionally_prepare_video(const LLParcel *parcelp); | 90 | void optionally_prepare_video(const LLParcel *parcelp); |
91 | void callback_prepare_video(S32 option, void* data); | 91 | void 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 | ||
1722 | void optionally_start_music(const std::string& music_url) | 1722 | void 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"> | ||
7327 | The 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"> | ||
7356 | Media/audio URLs for [DOMAIN] now [LISTED] | ||
7357 | </notification> | ||
7358 | |||
7359 | <notification | ||
7360 | icon="notifytip.tga" | ||
7361 | name="MediaBlocked" | ||
7362 | type="notifytip"> | ||
7363 | Media/audio URL blocked for [DOMAIN] | ||
7364 | </notification> | ||
7365 | |||
7366 | <notification | ||
7367 | icon="alertmodal.tga" | ||
7368 | name="MediaFiltersCleared" | ||
7369 | type="alertmodal"> | ||
7370 | The 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 | |||
44 | SLFloaterMediaFilter* SLFloaterMediaFilter::sInstance = NULL; | ||
45 | bool SLFloaterMediaFilter::sIsWhitelist = false; | ||
46 | |||
47 | SLFloaterMediaFilter::SLFloaterMediaFilter() : LLFloater(std::string("media filter")), mIsDirty(false) | ||
48 | { | ||
49 | LLUICtrlFactory::getInstance()->buildFloater(this, "floater_media_filter.xml"); | ||
50 | } | ||
51 | |||
52 | SLFloaterMediaFilter::~SLFloaterMediaFilter() | ||
53 | { | ||
54 | sInstance = NULL; | ||
55 | } | ||
56 | |||
57 | BOOL 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 | |||
78 | void 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 | |||
165 | void SLFloaterMediaFilter::setDirty() | ||
166 | { | ||
167 | if (sInstance) | ||
168 | { | ||
169 | sInstance->mIsDirty = true; | ||
170 | sInstance->draw(); | ||
171 | } | ||
172 | } | ||
173 | |||
174 | BOOL SLFloaterMediaFilter::instanceVisible() | ||
175 | { | ||
176 | if (sInstance) | ||
177 | { | ||
178 | return sInstance->getVisible(); | ||
179 | } | ||
180 | else | ||
181 | { | ||
182 | return FALSE; | ||
183 | } | ||
184 | } | ||
185 | |||
186 | void 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 | |||
206 | void SLFloaterMediaFilter::onClearLists(void* data) | ||
207 | { | ||
208 | LLViewerParcelMedia::clearDomainFilterList(); | ||
209 | } | ||
210 | |||
211 | void 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 | |||
230 | void 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 | |||
257 | void 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 | |||
276 | void 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 | |||
303 | void 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 | |||
39 | class LLScrollListCtrl; | ||
40 | class LLButton; | ||
41 | |||
42 | class SLFloaterMediaFilter : public LLFloater | ||
43 | { | ||
44 | public: | ||
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 | |||
61 | private: | ||
62 | static bool sIsWhitelist; | ||
63 | LLScrollListCtrl* mWhitelistSLC; | ||
64 | LLScrollListCtrl* mBlacklistSLC; | ||
65 | bool mIsDirty; | ||
66 | |||
67 | static SLFloaterMediaFilter* sInstance; | ||
68 | |||
69 | }; | ||
70 | #endif | ||