Merge Firestorm LGPL Lynx
commit
37b8d0a10e
1
.hgtags
1
.hgtags
|
|
@ -572,3 +572,4 @@ abcab37e1b29414ab8c03af9ca2ab489d809788a 5.0.7-release
|
|||
ad0e15543836d64d6399d28b32852510435e344a 5.1.0-release
|
||||
26d9e9bb166a9a417f35b1863223a597af8185fd 5.1.1-release
|
||||
2eb917875efdfe920680b9049302d0f03721245d 5.1.2-release
|
||||
7c00e5b6cb3d95712e9d8e29277c805bca2bda90 5.1.3-release
|
||||
|
|
|
|||
|
|
@ -756,9 +756,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>bbdea742f2a89bcd6360e61e01d6be93</string>
|
||||
<string>118987b1a5b56214cfdbd0c763e180da</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/8207/32592/dullahan-1.1.820_3.3071.1637.gcb6cf75-darwin64-508196.tar.bz2</string>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/15127/97748/dullahan-1.1.1080_3.3325.1750.gaabe4c4-darwin64-513449.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -792,9 +792,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>31e11a74e0d3f1e5e4036cb5fea8d944</string>
|
||||
<string>2ecc71350b30a1057091b9cd7af18b1c</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/8209/32599/dullahan-1.1.820_3.3071.1634.g9cc59c8-windows-508196.tar.bz2</string>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/15128/97755/dullahan-1.1.1080_3.3325.1750.gaabe4c4-windows-513449.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -804,16 +804,16 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>f965d244e7921c06ee79b68a4abcea3b</string>
|
||||
<string>2ed3e49388514dafb907c59a209d580e</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/8208/32602/dullahan-1.1.820_3.3071.1634.g9cc59c8-windows64-508196.tar.bz2</string>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/15129/97760/dullahan-1.1.1080_3.3325.1750.gaabe4c4-windows64-513449.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>1.1.820_3.3071.1634.g9cc59c8</string>
|
||||
<string>1.1.1080_3.3325.1750.gaabe4c4</string>
|
||||
</map>
|
||||
<key>elfio</key>
|
||||
<map>
|
||||
|
|
@ -3630,9 +3630,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>c5e6d9440e3a4a12102dd2bbb703963e</string>
|
||||
<string>e5635e173c75dc0675b48ab5f5e4868b</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/2225/4736/vlc_bin-2.2.4.502214-darwin64-502214.tar.bz2</string>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/12143/71451/vlc_bin-2.2.8.511703-darwin64-511703.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -3666,9 +3666,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>dc37f7cc77a62891bb9ae46c9e19f95e</string>
|
||||
<string>add560654a53cb1c554044a4fac3c718</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1219/2834/vlc_bin-2.2.4.501207-windows-501207.tar.bz2</string>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/12144/71458/vlc_bin-2.2.8.511703-windows-511703.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -3678,16 +3678,16 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>148ee599afeba9794de14ca433389504</string>
|
||||
<string>94bf04b49acc1e1bf2c06e2232f8a083</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1218/2829/vlc_bin-2.2.4.501207-windows64-501207.tar.bz2</string>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/12145/71463/vlc_bin-2.2.8.511703-windows64-511703.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>2.2.4.502214</string>
|
||||
<string>2.2.8.511703</string>
|
||||
</map>
|
||||
<key>xmlrpc-epi</key>
|
||||
<map>
|
||||
|
|
|
|||
|
|
@ -157,11 +157,9 @@ if (LINUX)
|
|||
if ( ${FORTIFY_SOURCE_RES} EQUAL 0 )
|
||||
add_definitions(-D_FORTIFY_SOURCE=2)
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS "-Wno-deprecated -Wno-unused-but-set-variable -Wno-unused-variable -Wno-placement-new ${CMAKE_CXX_FLAGS}")
|
||||
|
||||
# gcc 4.3 and above don't like the LL boost and also
|
||||
# cause warnings due to our use of deprecated headers
|
||||
add_definitions(-Wno-parentheses)
|
||||
|
||||
add_definitions(
|
||||
-D_REENTRANT
|
||||
|
|
@ -176,18 +174,9 @@ if (LINUX)
|
|||
-pthread
|
||||
)
|
||||
|
||||
# <FS:ND> Enable C++11 support + gnu extensions
|
||||
add_definitions(-std=gnu++11)
|
||||
# </FS:ND>
|
||||
|
||||
# <FS:ND> Enable old C++ ABI
|
||||
add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
|
||||
# </FS:ND>
|
||||
|
||||
# force this platform to accept TOS via external browser <FS:ND> No, do not.
|
||||
# add_definitions(-DEXTERNAL_TOS)
|
||||
|
||||
|
||||
add_definitions(-DAPPID=secondlife)
|
||||
add_compile_options(-fvisibility=hidden)
|
||||
# don't catch SIGCHLD in our base application class for the viewer - some of
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ include_directories(SYSTEM
|
|||
|
||||
set(llplugin_SOURCE_FILES
|
||||
llpluginclassmedia.cpp
|
||||
llplugincookiestore.cpp
|
||||
llplugininstance.cpp
|
||||
llpluginmessage.cpp
|
||||
llpluginmessagepipe.cpp
|
||||
|
|
@ -43,7 +42,6 @@ set(llplugin_HEADER_FILES
|
|||
|
||||
llpluginclassmedia.h
|
||||
llpluginclassmediaowner.h
|
||||
llplugincookiestore.h
|
||||
llplugininstance.h
|
||||
llpluginmessage.h
|
||||
llpluginmessageclasses.h
|
||||
|
|
@ -70,20 +68,3 @@ add_library (llplugin ${llplugin_SOURCE_FILES})
|
|||
|
||||
add_subdirectory(slplugin)
|
||||
|
||||
# Add tests
|
||||
if (LL_TESTS)
|
||||
include(LLAddBuildTest)
|
||||
# UNIT TESTS
|
||||
SET(llplugin_TEST_SOURCE_FILES
|
||||
llplugincookiestore.cpp
|
||||
)
|
||||
|
||||
# llplugincookiestore has a dependency on curl, so we need to link the curl library into the test.
|
||||
set_source_files_properties(
|
||||
llplugincookiestore.cpp
|
||||
PROPERTIES
|
||||
LL_TEST_ADDITIONAL_LIBRARIES "${CURL_LIBRARIES};${NGHTTP2_LIBRARIES}"
|
||||
)
|
||||
|
||||
LL_ADD_PROJECT_UNIT_TESTS(llplugin "${llplugin_TEST_SOURCE_FILES}")
|
||||
endif (LL_TESTS)
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@
|
|||
|
||||
#include "llpluginclassmedia.h"
|
||||
#include "llpluginmessageclasses.h"
|
||||
#include "llcontrol.h"
|
||||
|
||||
extern LLControlGroup gSavedSettings;
|
||||
|
||||
static int LOW_PRIORITY_TEXTURE_SIZE_DEFAULT = 256;
|
||||
|
||||
|
|
@ -794,15 +797,22 @@ F64 LLPluginClassMedia::getCPUUsage()
|
|||
return result;
|
||||
}
|
||||
|
||||
void LLPluginClassMedia::sendPickFileResponse(const std::string &file)
|
||||
void LLPluginClassMedia::sendPickFileResponse(const std::vector<std::string> files)
|
||||
{
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file_response");
|
||||
message.setValue("file", file);
|
||||
if(mPlugin && mPlugin->isBlocked())
|
||||
{
|
||||
// If the plugin sent a blocking pick-file request, the response should unblock it.
|
||||
message.setValueBoolean("blocking_response", true);
|
||||
}
|
||||
|
||||
LLSD file_list = LLSD::emptyArray();
|
||||
for (std::vector<std::string>::const_iterator in_iter = files.begin(); in_iter != files.end(); ++in_iter)
|
||||
{
|
||||
file_list.append(LLSD::String(*in_iter));
|
||||
}
|
||||
message.setValueLLSD("file_list", file_list);
|
||||
|
||||
sendMessage(message);
|
||||
}
|
||||
|
||||
|
|
@ -838,11 +848,17 @@ void LLPluginClassMedia::paste()
|
|||
sendMessage(message);
|
||||
}
|
||||
|
||||
void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path_cache, const std::string &user_data_path_cookies)
|
||||
void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path_cache,
|
||||
const std::string &user_data_path_cookies,
|
||||
const std::string &user_data_path_cef_log)
|
||||
{
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_user_data_path");
|
||||
message.setValue("cache_path", user_data_path_cache);
|
||||
message.setValue("cookies_path", user_data_path_cookies);
|
||||
message.setValue("cef_log_file", user_data_path_cef_log);
|
||||
|
||||
bool cef_verbose_log = gSavedSettings.getBOOL("CefVerboseLog");
|
||||
message.setValueBoolean("cef_verbose_log", cef_verbose_log);
|
||||
sendMessage(message);
|
||||
}
|
||||
|
||||
|
|
@ -1102,6 +1118,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
|
|||
}
|
||||
else if(message_name == "pick_file")
|
||||
{
|
||||
mIsMultipleFilePick = message.getValueBoolean("multiple_files");
|
||||
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PICK_FILE_REQUEST);
|
||||
}
|
||||
else if(message_name == "auth_request")
|
||||
|
|
@ -1163,7 +1180,12 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
|
|||
{
|
||||
mClickURL = message.getValue("uri");
|
||||
mClickTarget = message.getValue("target");
|
||||
//mClickUUID = message.getValue("uuid");
|
||||
|
||||
// need a link to have a UUID that identifies it to a system further
|
||||
// upstream - plugin could make it but we have access to LLUUID here
|
||||
// so why don't we use it
|
||||
mClickUUID = LLUUID::generateNewID().asString();
|
||||
|
||||
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF);
|
||||
}
|
||||
else if(message_name == "click_nofollow")
|
||||
|
|
@ -1178,13 +1200,6 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
|
|||
mStatusCode = message.getValueS32("status_code");
|
||||
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_ERROR_PAGE);
|
||||
}
|
||||
else if(message_name == "cookie_set")
|
||||
{
|
||||
if(mOwner)
|
||||
{
|
||||
mOwner->handleCookieSet(this, message.getValue("cookie"));
|
||||
}
|
||||
}
|
||||
else if(message_name == "close_request")
|
||||
{
|
||||
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLOSE_REQUEST);
|
||||
|
|
@ -1299,14 +1314,7 @@ void LLPluginClassMedia::clear_cookies()
|
|||
sendMessage(message);
|
||||
}
|
||||
|
||||
void LLPluginClassMedia::set_cookies(const std::string &cookies)
|
||||
{
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_cookies");
|
||||
message.setValue("cookies", cookies);
|
||||
sendMessage(message);
|
||||
}
|
||||
|
||||
void LLPluginClassMedia::enable_cookies(bool enable)
|
||||
void LLPluginClassMedia::cookies_enabled(bool enable)
|
||||
{
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "cookies_enabled");
|
||||
message.setValueBoolean("enable", enable);
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ public:
|
|||
|
||||
F64 getCPUUsage();
|
||||
|
||||
void sendPickFileResponse(const std::string &file);
|
||||
void sendPickFileResponse(const std::vector<std::string> files);
|
||||
|
||||
void sendAuthResponse(bool ok, const std::string &username, const std::string &password);
|
||||
|
||||
|
|
@ -195,7 +195,7 @@ public:
|
|||
bool canPaste() const { return mCanPaste; };
|
||||
|
||||
// These can be called before init(), and they will be queued and sent before the media init message.
|
||||
void setUserDataPath(const std::string &user_data_path_cache, const std::string &user_data_path_cookies);
|
||||
void setUserDataPath(const std::string &user_data_path_cache, const std::string &user_data_path_cookies, const std::string &user_data_path_cef_log);
|
||||
void setLanguageCode(const std::string &language_code);
|
||||
void setPluginsEnabled(const bool enabled);
|
||||
void setJavascriptEnabled(const bool enabled);
|
||||
|
|
@ -210,7 +210,7 @@ public:
|
|||
void clear_cache();
|
||||
void clear_cookies();
|
||||
void set_cookies(const std::string &cookies);
|
||||
void enable_cookies(bool enable);
|
||||
void cookies_enabled(bool enable);
|
||||
void proxy_setup(bool enable, const std::string &host = LLStringUtil::null, int port = 0);
|
||||
void browse_stop();
|
||||
void browse_reload(bool ignore_cache = false);
|
||||
|
|
@ -277,6 +277,9 @@ public:
|
|||
std::string getAuthURL() const { return mAuthURL; };
|
||||
std::string getAuthRealm() const { return mAuthRealm; };
|
||||
|
||||
// These are valid during MEDIA_EVENT_PICK_FILE_REQUEST
|
||||
bool getIsMultipleFilePick() const { return mIsMultipleFilePick; }
|
||||
|
||||
// These are valid during MEDIA_EVENT_LINK_HOVERED
|
||||
std::string getHoverText() const { return mHoverText; };
|
||||
std::string getHoverLink() const { return mHoverLink; };
|
||||
|
|
@ -435,6 +438,7 @@ protected:
|
|||
std::string mHoverText;
|
||||
std::string mHoverLink;
|
||||
std::string mFileDownloadFilename;
|
||||
bool mIsMultipleFilePick;
|
||||
|
||||
/////////////////////////////////////////
|
||||
// media_time class
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/**
|
||||
* @file llpluginclassmediaowner.h
|
||||
* @brief LLPluginClassMedia handles interaction with a plugin which knows about the "media" message class.
|
||||
*
|
||||
|
|
@ -6,21 +6,21 @@
|
|||
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
* @endcond
|
||||
|
|
@ -34,18 +34,17 @@
|
|||
#include <queue>
|
||||
|
||||
class LLPluginClassMedia;
|
||||
class LLPluginCookieStore;
|
||||
|
||||
class LLPluginClassMediaOwner
|
||||
{
|
||||
public:
|
||||
typedef enum
|
||||
{
|
||||
MEDIA_EVENT_CONTENT_UPDATED, // contents/dirty rect have updated
|
||||
MEDIA_EVENT_CONTENT_UPDATED, // contents/dirty rect have updated
|
||||
MEDIA_EVENT_TIME_DURATION_UPDATED, // current time and/or duration have updated
|
||||
MEDIA_EVENT_SIZE_CHANGED, // media size has changed
|
||||
MEDIA_EVENT_CURSOR_CHANGED, // plugin has requested a cursor change
|
||||
|
||||
|
||||
MEDIA_EVENT_NAVIGATE_BEGIN, // browser has begun navigation
|
||||
MEDIA_EVENT_NAVIGATE_COMPLETE, // browser has finished navigation
|
||||
MEDIA_EVENT_PROGRESS_UPDATED, // browser has updated loading progress
|
||||
|
|
@ -58,8 +57,8 @@ public:
|
|||
MEDIA_EVENT_CLOSE_REQUEST, // The plugin requested its window be closed (currently hooked up to javascript window.close in webkit)
|
||||
MEDIA_EVENT_PICK_FILE_REQUEST, // The plugin wants the user to pick a file
|
||||
MEDIA_EVENT_GEOMETRY_CHANGE, // The plugin requested its window geometry be changed (per the javascript window interface)
|
||||
|
||||
MEDIA_EVENT_PLUGIN_FAILED_LAUNCH, // The plugin failed to launch
|
||||
|
||||
MEDIA_EVENT_PLUGIN_FAILED_LAUNCH, // The plugin failed to launch
|
||||
MEDIA_EVENT_PLUGIN_FAILED, // The plugin died unexpectedly
|
||||
|
||||
MEDIA_EVENT_AUTH_REQUEST, // The plugin wants to display an auth dialog
|
||||
|
|
@ -69,9 +68,9 @@ public:
|
|||
MEDIA_EVENT_DEBUG_MESSAGE, // plugin sending back debug information for host to process
|
||||
|
||||
MEDIA_EVENT_LINK_HOVERED // Got a "link hovered" event from the plugin
|
||||
|
||||
|
||||
} EMediaEvent;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MEDIA_NONE, // Uninitialized -- no useful state
|
||||
|
|
@ -81,12 +80,11 @@ public:
|
|||
MEDIA_PLAYING, // playing (only for time-based media)
|
||||
MEDIA_PAUSED, // paused (only for time-based media)
|
||||
MEDIA_DONE // finished playing (only for time-based media)
|
||||
|
||||
|
||||
} EMediaStatus;
|
||||
|
||||
|
||||
virtual ~LLPluginClassMediaOwner() {};
|
||||
virtual void handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent /*event*/) {};
|
||||
virtual void handleCookieSet(LLPluginClassMedia* /*self*/, const std::string &/*cookie*/) {};
|
||||
};
|
||||
|
||||
#endif // LL_LLPLUGINCLASSMEDIAOWNER_H
|
||||
|
|
|
|||
|
|
@ -1,689 +0,0 @@
|
|||
/**
|
||||
* @file llplugincookiestore.cpp
|
||||
* @brief LLPluginCookieStore provides central storage for http cookies used by plugins
|
||||
*
|
||||
* @cond
|
||||
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
* @endcond
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llstl.h"
|
||||
#include "indra_constants.h"
|
||||
|
||||
#include "llplugincookiestore.h"
|
||||
#include <iostream>
|
||||
|
||||
// for curl_getdate() (apparently parsing RFC 1123 dates is hard)
|
||||
#include <curl/curl.h>
|
||||
|
||||
LLPluginCookieStore::LLPluginCookieStore():
|
||||
mHasChangedCookies(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LLPluginCookieStore::~LLPluginCookieStore()
|
||||
{
|
||||
clearCookies();
|
||||
}
|
||||
|
||||
|
||||
LLPluginCookieStore::Cookie::Cookie(const std::string &s, std::string::size_type cookie_start, std::string::size_type cookie_end):
|
||||
mCookie(s, cookie_start, cookie_end - cookie_start),
|
||||
mNameStart(0), mNameEnd(0),
|
||||
mValueStart(0), mValueEnd(0),
|
||||
mDomainStart(0), mDomainEnd(0),
|
||||
mPathStart(0), mPathEnd(0),
|
||||
mDead(false), mChanged(true)
|
||||
{
|
||||
}
|
||||
|
||||
LLPluginCookieStore::Cookie *LLPluginCookieStore::Cookie::createFromString(const std::string &s, std::string::size_type cookie_start, std::string::size_type cookie_end, const std::string &host)
|
||||
{
|
||||
Cookie *result = new Cookie(s, cookie_start, cookie_end);
|
||||
|
||||
if(!result->parse(host))
|
||||
{
|
||||
delete result;
|
||||
result = NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string LLPluginCookieStore::Cookie::getKey() const
|
||||
{
|
||||
std::string result;
|
||||
if(mDomainEnd > mDomainStart)
|
||||
{
|
||||
result += mCookie.substr(mDomainStart, mDomainEnd - mDomainStart);
|
||||
}
|
||||
result += ';';
|
||||
if(mPathEnd > mPathStart)
|
||||
{
|
||||
result += mCookie.substr(mPathStart, mPathEnd - mPathStart);
|
||||
}
|
||||
result += ';';
|
||||
result += mCookie.substr(mNameStart, mNameEnd - mNameStart);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string LLPluginCookieStore::Cookie::getDomain() const
|
||||
{
|
||||
std::string result;
|
||||
if(mDomainEnd > mDomainStart)
|
||||
{
|
||||
result += mCookie.substr(mDomainStart, mDomainEnd - mDomainStart);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool LLPluginCookieStore::Cookie::parse(const std::string &host)
|
||||
{
|
||||
bool first_field = true;
|
||||
|
||||
std::string::size_type cookie_end = mCookie.size();
|
||||
std::string::size_type field_start = 0;
|
||||
|
||||
LL_DEBUGS("CookieStoreParse") << "parsing cookie: " << mCookie << LL_ENDL;
|
||||
while(field_start < cookie_end)
|
||||
{
|
||||
// Finding the start of the next field requires honoring special quoting rules
|
||||
// see the definition of 'quoted-string' in rfc2616 for details
|
||||
std::string::size_type next_field_start = findFieldEnd(field_start);
|
||||
|
||||
// The end of this field should not include the terminating ';' or any trailing whitespace
|
||||
std::string::size_type field_end = mCookie.find_last_not_of("; ", next_field_start);
|
||||
if(field_end == std::string::npos || field_end < field_start)
|
||||
{
|
||||
// This field was empty or all whitespace. Set end = start so it shows as empty.
|
||||
field_end = field_start;
|
||||
}
|
||||
else if (field_end < next_field_start)
|
||||
{
|
||||
// we actually want the index of the char _after_ what 'last not of' found
|
||||
++field_end;
|
||||
}
|
||||
|
||||
// find the start of the actual name (skip separator and possible whitespace)
|
||||
std::string::size_type name_start = mCookie.find_first_not_of("; ", field_start);
|
||||
if(name_start == std::string::npos || name_start > next_field_start)
|
||||
{
|
||||
// Again, nothing but whitespace.
|
||||
name_start = field_start;
|
||||
}
|
||||
|
||||
// the name and value are separated by the first equals sign
|
||||
std::string::size_type name_value_sep = mCookie.find_first_of("=", name_start);
|
||||
if(name_value_sep == std::string::npos || name_value_sep > field_end)
|
||||
{
|
||||
// No separator found, so this is a field without an =
|
||||
name_value_sep = field_end;
|
||||
}
|
||||
|
||||
// the name end is before the name-value separator
|
||||
std::string::size_type name_end = mCookie.find_last_not_of("= ", name_value_sep);
|
||||
if(name_end == std::string::npos || name_end < name_start)
|
||||
{
|
||||
// I'm not sure how we'd hit this case... it seems like it would have to be an empty name.
|
||||
name_end = name_start;
|
||||
}
|
||||
else if (name_end < name_value_sep)
|
||||
{
|
||||
// we actually want the index of the char _after_ what 'last not of' found
|
||||
++name_end;
|
||||
}
|
||||
|
||||
// Value is between the name-value sep and the end of the field.
|
||||
std::string::size_type value_start = mCookie.find_first_not_of("= ", name_value_sep);
|
||||
if(value_start == std::string::npos || value_start > field_end)
|
||||
{
|
||||
// All whitespace or empty value
|
||||
value_start = field_end;
|
||||
}
|
||||
std::string::size_type value_end = mCookie.find_last_not_of("; ", field_end);
|
||||
if(value_end == std::string::npos || value_end < value_start)
|
||||
{
|
||||
// All whitespace or empty value
|
||||
value_end = value_start;
|
||||
}
|
||||
else if (value_end < field_end)
|
||||
{
|
||||
// we actually want the index of the char _after_ what 'last not of' found
|
||||
++value_end;
|
||||
}
|
||||
|
||||
LL_DEBUGS("CookieStoreParse")
|
||||
<< " field name: \"" << mCookie.substr(name_start, name_end - name_start)
|
||||
<< "\", value: \"" << mCookie.substr(value_start, value_end - value_start) << "\""
|
||||
<< LL_ENDL;
|
||||
|
||||
// See whether this field is one we know
|
||||
if(first_field)
|
||||
{
|
||||
// The first field is the name=value pair
|
||||
mNameStart = name_start;
|
||||
mNameEnd = name_end;
|
||||
mValueStart = value_start;
|
||||
mValueEnd = value_end;
|
||||
first_field = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Subsequent fields must come from the set in rfc2109
|
||||
if(matchName(name_start, name_end, "expires"))
|
||||
{
|
||||
std::string date_string(mCookie, value_start, value_end - value_start);
|
||||
// If the cookie contains an "expires" field, it MUST contain a parsable date.
|
||||
|
||||
// HACK: LLDate apparently can't PARSE an rfc1123-format date, even though it can GENERATE one.
|
||||
// The curl function curl_getdate can do this, but I'm hesitant to unilaterally introduce a curl dependency in LLDate.
|
||||
#if 1
|
||||
time_t date = curl_getdate(date_string.c_str(), NULL );
|
||||
mDate.secondsSinceEpoch((F64)date);
|
||||
LL_DEBUGS("CookieStoreParse") << " expire date parsed to: " << mDate.asRFC1123() << LL_ENDL;
|
||||
#else
|
||||
// This doesn't work (rfc1123-format dates cause it to fail)
|
||||
if(!mDate.fromString(date_string))
|
||||
{
|
||||
// Date failed to parse.
|
||||
LL_WARNS("CookieStoreParse") << "failed to parse cookie's expire date: " << date << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if(matchName(name_start, name_end, "domain"))
|
||||
{
|
||||
mDomainStart = value_start;
|
||||
mDomainEnd = value_end;
|
||||
}
|
||||
else if(matchName(name_start, name_end, "path"))
|
||||
{
|
||||
mPathStart = value_start;
|
||||
mPathEnd = value_end;
|
||||
}
|
||||
else if(matchName(name_start, name_end, "max-age"))
|
||||
{
|
||||
// TODO: how should we handle this?
|
||||
}
|
||||
else if(matchName(name_start, name_end, "secure"))
|
||||
{
|
||||
// We don't care about the value of this field (yet)
|
||||
}
|
||||
else if(matchName(name_start, name_end, "version"))
|
||||
{
|
||||
// We don't care about the value of this field (yet)
|
||||
}
|
||||
else if(matchName(name_start, name_end, "comment"))
|
||||
{
|
||||
// We don't care about the value of this field (yet)
|
||||
}
|
||||
else if(matchName(name_start, name_end, "httponly"))
|
||||
{
|
||||
// We don't care about the value of this field (yet)
|
||||
}
|
||||
else
|
||||
{
|
||||
// An unknown field is a parse failure
|
||||
LL_WARNS("CookieStoreParse") << "unexpected field name: " << mCookie.substr(name_start, name_end - name_start) << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// move on to the next field, skipping this field's separator and any leading whitespace
|
||||
field_start = mCookie.find_first_not_of("; ", next_field_start);
|
||||
}
|
||||
|
||||
// The cookie MUST have a name
|
||||
if(mNameEnd <= mNameStart)
|
||||
return false;
|
||||
|
||||
// If the cookie doesn't have a domain, add the current host as the domain.
|
||||
if(mDomainEnd <= mDomainStart)
|
||||
{
|
||||
if(host.empty())
|
||||
{
|
||||
// no domain and no current host -- this is a parse failure.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Figure out whether this cookie ended with a ";" or not...
|
||||
std::string::size_type last_char = mCookie.find_last_not_of(" ");
|
||||
if((last_char != std::string::npos) && (mCookie[last_char] != ';'))
|
||||
{
|
||||
mCookie += ";";
|
||||
}
|
||||
|
||||
mCookie += " domain=";
|
||||
mDomainStart = mCookie.size();
|
||||
mCookie += host;
|
||||
mDomainEnd = mCookie.size();
|
||||
|
||||
LL_DEBUGS("CookieStoreParse") << "added domain (" << mDomainStart << " to " << mDomainEnd << "), new cookie is: " << mCookie << LL_ENDL;
|
||||
}
|
||||
|
||||
// If the cookie doesn't have a path, add "/".
|
||||
if(mPathEnd <= mPathStart)
|
||||
{
|
||||
// Figure out whether this cookie ended with a ";" or not...
|
||||
std::string::size_type last_char = mCookie.find_last_not_of(" ");
|
||||
if((last_char != std::string::npos) && (mCookie[last_char] != ';'))
|
||||
{
|
||||
mCookie += ";";
|
||||
}
|
||||
|
||||
mCookie += " path=";
|
||||
mPathStart = mCookie.size();
|
||||
mCookie += "/";
|
||||
mPathEnd = mCookie.size();
|
||||
|
||||
LL_DEBUGS("CookieStoreParse") << "added path (" << mPathStart << " to " << mPathEnd << "), new cookie is: " << mCookie << LL_ENDL;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string::size_type LLPluginCookieStore::Cookie::findFieldEnd(std::string::size_type start, std::string::size_type end)
|
||||
{
|
||||
std::string::size_type result = start;
|
||||
|
||||
if(end == std::string::npos)
|
||||
end = mCookie.size();
|
||||
|
||||
bool in_quotes = false;
|
||||
for(; (result < end); result++)
|
||||
{
|
||||
switch(mCookie[result])
|
||||
{
|
||||
case '\\':
|
||||
if(in_quotes)
|
||||
result++; // The next character is backslash-quoted. Skip over it.
|
||||
break;
|
||||
case '"':
|
||||
in_quotes = !in_quotes;
|
||||
break;
|
||||
case ';':
|
||||
if(!in_quotes)
|
||||
return result;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we got here, no ';' was found.
|
||||
return end;
|
||||
}
|
||||
|
||||
bool LLPluginCookieStore::Cookie::matchName(std::string::size_type start, std::string::size_type end, const char *name)
|
||||
{
|
||||
// NOTE: this assumes 'name' is already in lowercase. The code which uses it should be able to arrange this...
|
||||
|
||||
while((start < end) && (*name != '\0'))
|
||||
{
|
||||
if(tolower(mCookie[start]) != *name)
|
||||
return false;
|
||||
|
||||
start++;
|
||||
name++;
|
||||
}
|
||||
|
||||
// iff both strings hit the end at the same time, they're equal.
|
||||
return ((start == end) && (*name == '\0'));
|
||||
}
|
||||
|
||||
std::string LLPluginCookieStore::getAllCookies()
|
||||
{
|
||||
std::stringstream result;
|
||||
writeAllCookies(result);
|
||||
return result.str();
|
||||
}
|
||||
|
||||
void LLPluginCookieStore::writeAllCookies(std::ostream& s)
|
||||
{
|
||||
cookie_map_t::iterator iter;
|
||||
for(iter = mCookies.begin(); iter != mCookies.end(); iter++)
|
||||
{
|
||||
// Don't return expired cookies
|
||||
if(!iter->second->isDead())
|
||||
{
|
||||
s << (iter->second->getCookie()) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::string LLPluginCookieStore::getPersistentCookies()
|
||||
{
|
||||
std::stringstream result;
|
||||
writePersistentCookies(result);
|
||||
return result.str();
|
||||
}
|
||||
|
||||
void LLPluginCookieStore::writePersistentCookies(std::ostream& s)
|
||||
{
|
||||
cookie_map_t::iterator iter;
|
||||
for(iter = mCookies.begin(); iter != mCookies.end(); iter++)
|
||||
{
|
||||
// Don't return expired cookies or session cookies
|
||||
if(!iter->second->isDead() && !iter->second->isSessionCookie())
|
||||
{
|
||||
s << iter->second->getCookie() << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string LLPluginCookieStore::getChangedCookies(bool clear_changed)
|
||||
{
|
||||
std::stringstream result;
|
||||
writeChangedCookies(result, clear_changed);
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
void LLPluginCookieStore::writeChangedCookies(std::ostream& s, bool clear_changed)
|
||||
{
|
||||
if(mHasChangedCookies)
|
||||
{
|
||||
LL_DEBUGS() << "returning changed cookies: " << LL_ENDL;
|
||||
cookie_map_t::iterator iter;
|
||||
for(iter = mCookies.begin(); iter != mCookies.end(); )
|
||||
{
|
||||
cookie_map_t::iterator next = iter;
|
||||
next++;
|
||||
|
||||
// Only return cookies marked as "changed"
|
||||
if(iter->second->isChanged())
|
||||
{
|
||||
s << iter->second->getCookie() << "\n";
|
||||
|
||||
LL_DEBUGS() << " " << iter->second->getCookie() << LL_ENDL;
|
||||
|
||||
// If requested, clear the changed mark
|
||||
if(clear_changed)
|
||||
{
|
||||
if(iter->second->isDead())
|
||||
{
|
||||
// If this cookie was previously marked dead, it needs to be removed entirely.
|
||||
delete iter->second;
|
||||
mCookies.erase(iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not dead, just mark as not changed.
|
||||
iter->second->setChanged(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iter = next;
|
||||
}
|
||||
}
|
||||
|
||||
if(clear_changed)
|
||||
mHasChangedCookies = false;
|
||||
}
|
||||
|
||||
void LLPluginCookieStore::setAllCookies(const std::string &cookies, bool mark_changed)
|
||||
{
|
||||
clearCookies();
|
||||
setCookies(cookies, mark_changed);
|
||||
}
|
||||
|
||||
void LLPluginCookieStore::readAllCookies(std::istream& s, bool mark_changed)
|
||||
{
|
||||
clearCookies();
|
||||
readCookies(s, mark_changed);
|
||||
}
|
||||
|
||||
void LLPluginCookieStore::setCookies(const std::string &cookies, bool mark_changed)
|
||||
{
|
||||
std::string::size_type start = 0;
|
||||
|
||||
while(start != std::string::npos)
|
||||
{
|
||||
std::string::size_type end = cookies.find_first_of("\r\n", start);
|
||||
if(end > start)
|
||||
{
|
||||
// The line is non-empty. Try to create a cookie from it.
|
||||
setOneCookie(cookies, start, end, mark_changed);
|
||||
}
|
||||
start = cookies.find_first_not_of("\r\n ", end);
|
||||
}
|
||||
}
|
||||
|
||||
void LLPluginCookieStore::setCookiesFromHost(const std::string &cookies, const std::string &host, bool mark_changed)
|
||||
{
|
||||
std::string::size_type start = 0;
|
||||
|
||||
while(start != std::string::npos)
|
||||
{
|
||||
std::string::size_type end = cookies.find_first_of("\r\n", start);
|
||||
if(end > start)
|
||||
{
|
||||
// The line is non-empty. Try to create a cookie from it.
|
||||
setOneCookie(cookies, start, end, mark_changed, host);
|
||||
}
|
||||
start = cookies.find_first_not_of("\r\n ", end);
|
||||
}
|
||||
}
|
||||
|
||||
void LLPluginCookieStore::readCookies(std::istream& s, bool mark_changed)
|
||||
{
|
||||
std::string line;
|
||||
while(s.good() && !s.eof())
|
||||
{
|
||||
std::getline(s, line);
|
||||
if(!line.empty())
|
||||
{
|
||||
// Try to create a cookie from this line.
|
||||
setOneCookie(line, 0, std::string::npos, mark_changed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string LLPluginCookieStore::quoteString(const std::string &s)
|
||||
{
|
||||
std::stringstream result;
|
||||
|
||||
result << '"';
|
||||
|
||||
for(std::string::size_type i = 0; i < s.size(); ++i)
|
||||
{
|
||||
char c = s[i];
|
||||
switch(c)
|
||||
{
|
||||
// All these separators need to be quoted in HTTP headers, according to section 2.2 of rfc 2616:
|
||||
case '(': case ')': case '<': case '>': case '@':
|
||||
case ',': case ';': case ':': case '\\': case '"':
|
||||
case '/': case '[': case ']': case '?': case '=':
|
||||
case '{': case '}': case ' ': case '\t':
|
||||
result << '\\';
|
||||
break;
|
||||
}
|
||||
|
||||
result << c;
|
||||
}
|
||||
|
||||
result << '"';
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string LLPluginCookieStore::unquoteString(const std::string &s)
|
||||
{
|
||||
std::stringstream result;
|
||||
|
||||
bool in_quotes = false;
|
||||
|
||||
for(std::string::size_type i = 0; i < s.size(); ++i)
|
||||
{
|
||||
char c = s[i];
|
||||
switch(c)
|
||||
{
|
||||
case '\\':
|
||||
if(in_quotes)
|
||||
{
|
||||
// The next character is backslash-quoted. Pass it through untouched.
|
||||
++i;
|
||||
if(i < s.size())
|
||||
{
|
||||
result << s[i];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case '"':
|
||||
in_quotes = !in_quotes;
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
result << c;
|
||||
}
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
// The flow for deleting a cookie is non-obvious enough that I should call it out here...
|
||||
// Deleting a cookie is done by setting a cookie with the same name, path, and domain, but with an expire timestamp in the past.
|
||||
// (This is exactly how a web server tells a browser to delete a cookie.)
|
||||
// When deleting with mark_changed set to true, this replaces the existing cookie in the list with an entry that's marked both dead and changed.
|
||||
// Some time later when writeChangedCookies() is called with clear_changed set to true, the dead cookie is deleted from the list after being returned, so that the
|
||||
// delete operation (in the form of the expired cookie) is passed along.
|
||||
void LLPluginCookieStore::setOneCookie(const std::string &s, std::string::size_type cookie_start, std::string::size_type cookie_end, bool mark_changed, const std::string &host)
|
||||
{
|
||||
Cookie *cookie = Cookie::createFromString(s, cookie_start, cookie_end, host);
|
||||
if(cookie)
|
||||
{
|
||||
LL_DEBUGS("CookieStoreUpdate") << "setting cookie: " << cookie->getCookie() << LL_ENDL;
|
||||
|
||||
// Create a key for this cookie
|
||||
std::string key = cookie->getKey();
|
||||
|
||||
// Check to see whether this cookie should have expired
|
||||
if(!cookie->isSessionCookie() && (cookie->getDate() < LLDate::now()))
|
||||
{
|
||||
// This cookie has expired.
|
||||
if(mark_changed)
|
||||
{
|
||||
// If we're marking cookies as changed, we should keep it anyway since we'll need to send it out with deltas.
|
||||
cookie->setDead(true);
|
||||
LL_DEBUGS("CookieStoreUpdate") << " marking dead" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we're not marking cookies as changed, we don't need to keep this cookie at all.
|
||||
// If the cookie was already in the list, delete it.
|
||||
removeCookie(key);
|
||||
|
||||
delete cookie;
|
||||
cookie = NULL;
|
||||
|
||||
LL_DEBUGS("CookieStoreUpdate") << " removing" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
if(cookie)
|
||||
{
|
||||
// If it already exists in the map, replace it.
|
||||
cookie_map_t::iterator iter = mCookies.find(key);
|
||||
if(iter != mCookies.end())
|
||||
{
|
||||
if(iter->second->getCookie() == cookie->getCookie())
|
||||
{
|
||||
// The new cookie is identical to the old -- don't mark as changed.
|
||||
// Just leave the old one in the map.
|
||||
delete cookie;
|
||||
cookie = NULL;
|
||||
|
||||
LL_DEBUGS("CookieStoreUpdate") << " unchanged" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// A matching cookie was already in the map. Replace it.
|
||||
delete iter->second;
|
||||
iter->second = cookie;
|
||||
|
||||
cookie->setChanged(mark_changed);
|
||||
if(mark_changed)
|
||||
mHasChangedCookies = true;
|
||||
|
||||
LL_DEBUGS("CookieStoreUpdate") << " replacing" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The cookie wasn't in the map. Insert it.
|
||||
mCookies.insert(std::make_pair(key, cookie));
|
||||
|
||||
cookie->setChanged(mark_changed);
|
||||
if(mark_changed)
|
||||
mHasChangedCookies = true;
|
||||
|
||||
LL_DEBUGS("CookieStoreUpdate") << " adding" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("CookieStoreUpdate") << "failed to parse cookie: " << s.substr(cookie_start, cookie_end - cookie_start) << LL_ENDL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void LLPluginCookieStore::clearCookies()
|
||||
{
|
||||
std::for_each(mCookies.begin(), mCookies.end(), DeletePairedPointer());
|
||||
mCookies.clear();
|
||||
}
|
||||
|
||||
void LLPluginCookieStore::removeCookie(const std::string &key)
|
||||
{
|
||||
cookie_map_t::iterator iter = mCookies.find(key);
|
||||
if(iter != mCookies.end())
|
||||
{
|
||||
delete iter->second;
|
||||
mCookies.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
void LLPluginCookieStore::removeCookiesByDomain(const std::string &domain)
|
||||
{
|
||||
cookie_map_t::iterator iter = mCookies.begin();
|
||||
while(iter != mCookies.end())
|
||||
{
|
||||
if(iter->second->getDomain() == domain)
|
||||
{
|
||||
cookie_map_t::iterator doErase = iter;
|
||||
iter++;
|
||||
delete doErase->second;
|
||||
mCookies.erase(doErase);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
/**
|
||||
* @file llplugincookiestore.h
|
||||
* @brief LLPluginCookieStore provides central storage for http cookies used by plugins
|
||||
*
|
||||
* @cond
|
||||
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
* @endcond
|
||||
*/
|
||||
|
||||
#ifndef LL_LLPLUGINCOOKIESTORE_H
|
||||
#define LL_LLPLUGINCOOKIESTORE_H
|
||||
|
||||
#include "lldate.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
class LLPluginCookieStore
|
||||
{
|
||||
LOG_CLASS(LLPluginCookieStore);
|
||||
public:
|
||||
LLPluginCookieStore();
|
||||
~LLPluginCookieStore();
|
||||
|
||||
// gets all cookies currently in storage -- use when initializing a plugin
|
||||
std::string getAllCookies();
|
||||
void writeAllCookies(std::ostream& s);
|
||||
|
||||
// gets only persistent cookies (i.e. not session cookies) -- use when writing cookies to a file
|
||||
std::string getPersistentCookies();
|
||||
void writePersistentCookies(std::ostream& s);
|
||||
|
||||
// gets cookies which are marked as "changed" -- use when sending periodic updates to plugins
|
||||
std::string getChangedCookies(bool clear_changed = true);
|
||||
void writeChangedCookies(std::ostream& s, bool clear_changed = true);
|
||||
|
||||
// (re)initializes internal data structures and bulk-sets cookies -- use when reading cookies from a file
|
||||
void setAllCookies(const std::string &cookies, bool mark_changed = false);
|
||||
void readAllCookies(std::istream& s, bool mark_changed = false);
|
||||
|
||||
// sets one or more cookies (without reinitializing anything) -- use when receiving cookies from a plugin
|
||||
void setCookies(const std::string &cookies, bool mark_changed = true);
|
||||
void readCookies(std::istream& s, bool mark_changed = true);
|
||||
|
||||
// sets one or more cookies (without reinitializing anything), supplying a hostname the cookies came from -- use when setting a cookie manually
|
||||
void setCookiesFromHost(const std::string &cookies, const std::string &host, bool mark_changed = true);
|
||||
|
||||
// quote or unquote a string as per the definition of 'quoted-string' in rfc2616
|
||||
static std::string quoteString(const std::string &s);
|
||||
static std::string unquoteString(const std::string &s);
|
||||
|
||||
void removeCookiesByDomain(const std::string &domain);
|
||||
|
||||
private:
|
||||
|
||||
void setOneCookie(const std::string &s, std::string::size_type cookie_start, std::string::size_type cookie_end, bool mark_changed, const std::string &host = LLStringUtil::null);
|
||||
|
||||
class Cookie
|
||||
{
|
||||
public:
|
||||
static Cookie *createFromString(const std::string &s, std::string::size_type cookie_start = 0, std::string::size_type cookie_end = std::string::npos, const std::string &host = LLStringUtil::null);
|
||||
|
||||
// Construct a string from the cookie that uniquely represents it, to be used as a key in a std::map.
|
||||
std::string getKey() const;
|
||||
std::string getDomain() const;
|
||||
|
||||
const std::string &getCookie() const { return mCookie; };
|
||||
bool isSessionCookie() const { return mDate.isNull(); };
|
||||
|
||||
bool isDead() const { return mDead; };
|
||||
void setDead(bool dead) { mDead = dead; };
|
||||
|
||||
bool isChanged() const { return mChanged; };
|
||||
void setChanged(bool changed) { mChanged = changed; };
|
||||
|
||||
const LLDate &getDate() const { return mDate; };
|
||||
|
||||
private:
|
||||
Cookie(const std::string &s, std::string::size_type cookie_start = 0, std::string::size_type cookie_end = std::string::npos);
|
||||
bool parse(const std::string &host);
|
||||
std::string::size_type findFieldEnd(std::string::size_type start = 0, std::string::size_type end = std::string::npos);
|
||||
bool matchName(std::string::size_type start, std::string::size_type end, const char *name);
|
||||
|
||||
std::string mCookie; // The full cookie, in RFC 2109 string format
|
||||
LLDate mDate; // The expiration date of the cookie. For session cookies, this will be a null date (mDate.isNull() is true).
|
||||
// Start/end indices of various parts of the cookie string. Stored as indices into the string to save space and time.
|
||||
std::string::size_type mNameStart, mNameEnd;
|
||||
std::string::size_type mValueStart, mValueEnd;
|
||||
std::string::size_type mDomainStart, mDomainEnd;
|
||||
std::string::size_type mPathStart, mPathEnd;
|
||||
bool mDead;
|
||||
bool mChanged;
|
||||
};
|
||||
|
||||
typedef std::map<std::string, Cookie*> cookie_map_t;
|
||||
|
||||
cookie_map_t mCookies;
|
||||
bool mHasChangedCookies;
|
||||
|
||||
void clearCookies();
|
||||
void removeCookie(const std::string &key);
|
||||
};
|
||||
|
||||
#endif // LL_LLPLUGINCOOKIESTORE_H
|
||||
|
|
@ -1,207 +0,0 @@
|
|||
/**
|
||||
* @file llplugincookiestore_test.cpp
|
||||
* @brief Unit tests for LLPluginCookieStore.
|
||||
*
|
||||
* @cond
|
||||
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
* @endcond
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include <list>
|
||||
#include "../test/lltut.h"
|
||||
|
||||
#include "../llplugincookiestore.h"
|
||||
|
||||
|
||||
namespace tut
|
||||
{
|
||||
// Main Setup
|
||||
struct LLPluginCookieStoreFixture
|
||||
{
|
||||
LLPluginCookieStoreFixture()
|
||||
{
|
||||
// We need dates definitively in the past and the future to properly test cookie expiration.
|
||||
LLDate now = LLDate::now();
|
||||
LLDate past(now.secondsSinceEpoch() - (60.0 * 60.0 * 24.0)); // 1 day in the past
|
||||
LLDate future(now.secondsSinceEpoch() + (60.0 * 60.0 * 24.0)); // 1 day in the future
|
||||
|
||||
mPastString = past.asRFC1123();
|
||||
mFutureString = future.asRFC1123();
|
||||
}
|
||||
|
||||
std::string mPastString;
|
||||
std::string mFutureString;
|
||||
LLPluginCookieStore mCookieStore;
|
||||
|
||||
// List of cookies used for validation
|
||||
std::list<std::string> mCookies;
|
||||
|
||||
// This sets up mCookies from a string returned by one of the functions in LLPluginCookieStore
|
||||
void setCookies(const std::string &cookies)
|
||||
{
|
||||
mCookies.clear();
|
||||
std::string::size_type start = 0;
|
||||
|
||||
while(start != std::string::npos)
|
||||
{
|
||||
std::string::size_type end = cookies.find_first_of("\r\n", start);
|
||||
if(end > start)
|
||||
{
|
||||
std::string line(cookies, start, end - start);
|
||||
if(line.find_first_not_of("\r\n\t ") != std::string::npos)
|
||||
{
|
||||
// The line has some non-whitespace characters. Save it to the list.
|
||||
mCookies.push_back(std::string(cookies, start, end - start));
|
||||
}
|
||||
}
|
||||
start = cookies.find_first_not_of("\r\n ", end);
|
||||
}
|
||||
}
|
||||
|
||||
// This ensures that a cookie matching the one passed is in the list.
|
||||
void ensureCookie(const std::string &cookie)
|
||||
{
|
||||
std::list<std::string>::iterator iter;
|
||||
for(iter = mCookies.begin(); iter != mCookies.end(); iter++)
|
||||
{
|
||||
if(*iter == cookie)
|
||||
{
|
||||
// Found the cookie
|
||||
// TODO: this should do a smarter equality comparison on the two cookies, instead of just a string compare.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Didn't find this cookie
|
||||
std::string message = "cookie not found: ";
|
||||
message += cookie;
|
||||
ensure(message, false);
|
||||
}
|
||||
|
||||
// This ensures that the number of cookies in the list matches what's expected.
|
||||
void ensureSize(const std::string &message, size_t size)
|
||||
{
|
||||
if(mCookies.size() != size)
|
||||
{
|
||||
std::stringstream full_message;
|
||||
|
||||
full_message << message << " (expected " << size << ", actual " << mCookies.size() << ")";
|
||||
ensure(full_message.str(), false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef test_group<LLPluginCookieStoreFixture> factory;
|
||||
typedef factory::object object;
|
||||
factory tf("LLPluginCookieStore");
|
||||
|
||||
// Tests
|
||||
template<> template<>
|
||||
void object::test<1>()
|
||||
{
|
||||
// Test 1: cookie uniqueness and update lists.
|
||||
// Valid, distinct cookies:
|
||||
|
||||
std::string cookie01 = "cookieA=value; domain=example.com; path=/";
|
||||
std::string cookie02 = "cookieB=value; Domain=example.com; Path=/; Max-Age=10; Secure; Version=1; Comment=foo!; HTTPOnly"; // cookie with every supported field, in different cases.
|
||||
std::string cookie03 = "cookieA=value; domain=foo.example.com; path=/"; // different domain
|
||||
std::string cookie04 = "cookieA=value; domain=example.com; path=/bar/"; // different path
|
||||
std::string cookie05 = "cookieC; domain=example.com; path=/"; // empty value
|
||||
std::string cookie06 = "cookieD=value; domain=example.com; path=/; expires="; // different name, persistent cookie
|
||||
cookie06 += mFutureString;
|
||||
|
||||
mCookieStore.setCookies(cookie01);
|
||||
mCookieStore.setCookies(cookie02);
|
||||
mCookieStore.setCookies(cookie03);
|
||||
mCookieStore.setCookies(cookie04);
|
||||
mCookieStore.setCookies(cookie05);
|
||||
mCookieStore.setCookies(cookie06);
|
||||
|
||||
// Invalid cookies (these will get parse errors and not be added to the store)
|
||||
|
||||
std::string badcookie01 = "cookieD=value; domain=example.com; path=/; foo=bar"; // invalid field name
|
||||
std::string badcookie02 = "cookieE=value; path=/"; // no domain
|
||||
|
||||
mCookieStore.setCookies(badcookie01);
|
||||
mCookieStore.setCookies(badcookie02);
|
||||
|
||||
// All cookies added so far should have been marked as "changed"
|
||||
setCookies(mCookieStore.getChangedCookies());
|
||||
ensureSize("count of changed cookies", 6);
|
||||
ensureCookie(cookie01);
|
||||
ensureCookie(cookie02);
|
||||
ensureCookie(cookie03);
|
||||
ensureCookie(cookie04);
|
||||
ensureCookie(cookie05);
|
||||
ensureCookie(cookie06);
|
||||
|
||||
// Save off the current state of the cookie store (we'll restore it later)
|
||||
std::string savedCookies = mCookieStore.getAllCookies();
|
||||
|
||||
// Test replacing cookies
|
||||
std::string cookie01a = "cookieA=newvalue; domain=example.com; path=/"; // updated value
|
||||
std::string cookie02a = "cookieB=newvalue; domain=example.com; path=/; expires="; // remove cookie (by setting an expire date in the past)
|
||||
cookie02a += mPastString;
|
||||
|
||||
mCookieStore.setCookies(cookie01a);
|
||||
mCookieStore.setCookies(cookie02a);
|
||||
|
||||
// test for getting changed cookies
|
||||
setCookies(mCookieStore.getChangedCookies());
|
||||
ensureSize("count of updated cookies", 2);
|
||||
ensureCookie(cookie01a);
|
||||
ensureCookie(cookie02a);
|
||||
|
||||
// and for the state of the store after getting changed cookies
|
||||
setCookies(mCookieStore.getAllCookies());
|
||||
ensureSize("count of valid cookies", 5);
|
||||
ensureCookie(cookie01a);
|
||||
ensureCookie(cookie03);
|
||||
ensureCookie(cookie04);
|
||||
ensureCookie(cookie05);
|
||||
ensureCookie(cookie06);
|
||||
|
||||
// Check that only the persistent cookie is returned here
|
||||
setCookies(mCookieStore.getPersistentCookies());
|
||||
ensureSize("count of persistent cookies", 1);
|
||||
ensureCookie(cookie06);
|
||||
|
||||
// Restore the cookie store to a previous state and verify
|
||||
mCookieStore.setAllCookies(savedCookies);
|
||||
|
||||
// Since setAllCookies defaults to not marking cookies as changed, this list should be empty.
|
||||
setCookies(mCookieStore.getChangedCookies());
|
||||
ensureSize("count of changed cookies after restore", 0);
|
||||
|
||||
// Verify that the restore worked as it should have.
|
||||
setCookies(mCookieStore.getAllCookies());
|
||||
ensureSize("count of restored cookies", 6);
|
||||
ensureCookie(cookie01);
|
||||
ensureCookie(cookie02);
|
||||
ensureCookie(cookie03);
|
||||
ensureCookie(cookie04);
|
||||
ensureCookie(cookie05);
|
||||
ensureCookie(cookie06);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -350,7 +350,7 @@ LLUrlEntryInvalidSLURL::LLUrlEntryInvalidSLURL()
|
|||
{
|
||||
// <FS:Ansariel> Inworldz special
|
||||
//mPattern = boost::regex("(http://(maps.secondlife.com|slurl.com)/secondlife/|secondlife://(/app/(worldmap|teleport)/)?)[^ /]+(/-?[0-9]+){1,3}(/?(\\?title|\\?img|\\?msg)=\\S*)?/?",
|
||||
mPattern = boost::regex("(http://(maps.secondlife.com|slurl.com)/secondlife/|(secondlife|inworldz|iw)://(/app/(worldmap|teleport)/)?)[^ /]+(/-?[0-9]+){1,3}(/?(\\?title|\\?img|\\?msg)=\\S*)?/?",
|
||||
mPattern = boost::regex("(https?://(maps.secondlife.com|slurl.com)/secondlife/|(secondlife|inworldz|iw)://(/app/(worldmap|teleport)/)?)[^ /]+(/-?[0-9]+){1,3}(/?(\\?title|\\?img|\\?msg)=\\S*)?/?",
|
||||
boost::regex::perl|boost::regex::icase);
|
||||
mMenuName = "menu_url_http.xml";
|
||||
mTooltip = LLTrans::getString("TooltipHttpUrl");
|
||||
|
|
@ -437,7 +437,7 @@ bool LLUrlEntryInvalidSLURL::isSLURLvalid(const std::string &url) const
|
|||
LLUrlEntrySLURL::LLUrlEntrySLURL()
|
||||
{
|
||||
// see http://slurl.com/about.php for details on the SLURL format
|
||||
mPattern = boost::regex("http://(maps.secondlife.com|slurl.com)/secondlife/[^ /]+(/\\d+){0,3}(/?(\\?title|\\?img|\\?msg)=\\S*)?/?",
|
||||
mPattern = boost::regex("https?://(maps.secondlife.com|slurl.com)/secondlife/[^ /]+(/\\d+){0,3}(/?(\\?title|\\?img|\\?msg)=\\S*)?/?",
|
||||
boost::regex::perl|boost::regex::icase);
|
||||
mMenuName = "menu_url_slurl.xml";
|
||||
mTooltip = LLTrans::getString("TooltipSLURL");
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "media_plugin_base.h"
|
||||
|
||||
#include <functional>
|
||||
#include <chrono>
|
||||
|
||||
#include "dullahan.h"
|
||||
|
||||
|
|
@ -64,12 +65,12 @@ private:
|
|||
void onLoadStartCallback();
|
||||
void onRequestExitCallback();
|
||||
void onLoadEndCallback(int httpStatusCode);
|
||||
void onLoadError(int status, const std::string error_text);
|
||||
void onAddressChangeCallback(std::string url);
|
||||
void onNavigateURLCallback(std::string url, std::string target);
|
||||
void onOpenPopupCallback(std::string url, std::string target);
|
||||
bool onHTTPAuthCallback(const std::string host, const std::string realm, std::string& username, std::string& password);
|
||||
void onCursorChangedCallback(dullahan::ECursorType type);
|
||||
void onFileDownloadCallback(std::string filename);
|
||||
const std::string onFileDialogCallback();
|
||||
const std::vector<std::string> onFileDialog(dullahan::EFileDialogType dialog_type, const std::string dialog_title, const std::string default_file, const std::string dialog_accept_filter, bool& use_default);
|
||||
|
||||
void postDebugMessage(const std::string& msg);
|
||||
void authResponse(LLPluginMessage &message);
|
||||
|
|
@ -95,7 +96,9 @@ private:
|
|||
bool mCanPaste;
|
||||
std::string mCachePath;
|
||||
std::string mCookiePath;
|
||||
std::string mPickedFile;
|
||||
std::string mCefLogFile;
|
||||
bool mCefLogVerbose;
|
||||
std::vector<std::string> mPickedFiles;
|
||||
VolumeCatcher mVolumeCatcher;
|
||||
F32 mCurVolume;
|
||||
dullahan* mCEFLib;
|
||||
|
|
@ -115,7 +118,7 @@ MediaPluginBase(host_send_func, host_user_data)
|
|||
mCookiesEnabled = true;
|
||||
mPluginsEnabled = false;
|
||||
mJavascriptEnabled = true;
|
||||
mDisableGPU = true;
|
||||
mDisableGPU = false;
|
||||
mUserAgentSubtring = "";
|
||||
mAuthUsername = "";
|
||||
mAuthPassword = "";
|
||||
|
|
@ -125,7 +128,9 @@ MediaPluginBase(host_send_func, host_user_data)
|
|||
mCanPaste = false;
|
||||
mCachePath = "";
|
||||
mCookiePath = "";
|
||||
mPickedFile = "";
|
||||
mCefLogFile = "";
|
||||
mCefLogVerbose = false;
|
||||
mPickedFiles.clear();
|
||||
mCurVolume = 0.0;
|
||||
|
||||
mCEFLib = new dullahan();
|
||||
|
|
@ -166,6 +171,10 @@ void MediaPluginCEF::onPageChangedCallback(const unsigned char* pixels, int x, i
|
|||
{
|
||||
memcpy(mPixels, pixels, mWidth * mHeight * mDepth);
|
||||
}
|
||||
else
|
||||
{
|
||||
mCEFLib->setSize(mWidth, mHeight);
|
||||
}
|
||||
setDirty(0, 0, mWidth, mHeight);
|
||||
}
|
||||
}
|
||||
|
|
@ -210,6 +219,21 @@ void MediaPluginCEF::onLoadStartCallback()
|
|||
sendMessage(message);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void MediaPluginCEF::onLoadError(int status, const std::string error_text)
|
||||
{
|
||||
std::stringstream msg;
|
||||
|
||||
msg << "<b>Loading error!</b>";
|
||||
msg << "<p>";
|
||||
msg << "Message: " << error_text;
|
||||
msg << "<br>";
|
||||
msg << "Code: " << status;
|
||||
|
||||
mCEFLib->showBrowserMessage(msg.str());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void MediaPluginCEF::onRequestExitCallback()
|
||||
|
|
@ -243,12 +267,11 @@ void MediaPluginCEF::onAddressChangeCallback(std::string url)
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void MediaPluginCEF::onNavigateURLCallback(std::string url, std::string target)
|
||||
void MediaPluginCEF::onOpenPopupCallback(std::string url, std::string target)
|
||||
{
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_href");
|
||||
message.setValue("uri", url);
|
||||
message.setValue("target", target);
|
||||
message.setValue("uuid", ""); // not used right now
|
||||
sendMessage(message);
|
||||
}
|
||||
|
||||
|
|
@ -287,30 +310,52 @@ bool MediaPluginCEF::onHTTPAuthCallback(const std::string host, const std::strin
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void MediaPluginCEF::onFileDownloadCallback(const std::string filename)
|
||||
const std::vector<std::string> MediaPluginCEF::onFileDialog(dullahan::EFileDialogType dialog_type, const std::string dialog_title, const std::string default_file, std::string dialog_accept_filter, bool& use_default)
|
||||
{
|
||||
mAuthOK = false;
|
||||
// do not use the default CEF file picker
|
||||
use_default = false;
|
||||
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "file_download");
|
||||
message.setValue("filename", filename);
|
||||
if (dialog_type == dullahan::FD_OPEN_FILE)
|
||||
{
|
||||
mPickedFiles.clear();
|
||||
|
||||
sendMessage(message);
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file");
|
||||
message.setValueBoolean("blocking_request", true);
|
||||
message.setValueBoolean("multiple_files", false);
|
||||
|
||||
sendMessage(message);
|
||||
|
||||
return mPickedFiles;
|
||||
}
|
||||
else if (dialog_type == dullahan::FD_OPEN_MULTIPLE_FILES)
|
||||
{
|
||||
mPickedFiles.clear();
|
||||
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file");
|
||||
message.setValueBoolean("blocking_request", true);
|
||||
message.setValueBoolean("multiple_files", true);
|
||||
|
||||
sendMessage(message);
|
||||
|
||||
return mPickedFiles;
|
||||
}
|
||||
else if (dialog_type == dullahan::FD_SAVE_FILE)
|
||||
{
|
||||
mAuthOK = false;
|
||||
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "file_download");
|
||||
message.setValue("filename", default_file);
|
||||
|
||||
sendMessage(message);
|
||||
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
const std::string MediaPluginCEF::onFileDialogCallback()
|
||||
{
|
||||
mPickedFile.clear();
|
||||
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file");
|
||||
message.setValueBoolean("blocking_request", true);
|
||||
|
||||
sendMessage(message);
|
||||
|
||||
return mPickedFile;
|
||||
}
|
||||
|
||||
void MediaPluginCEF::onCursorChangedCallback(dullahan::ECursorType type)
|
||||
{
|
||||
std::string name = "";
|
||||
|
|
@ -343,6 +388,8 @@ void MediaPluginCEF::onCursorChangedCallback(dullahan::ECursorType type)
|
|||
sendMessage(message);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void MediaPluginCEF::authResponse(LLPluginMessage &message)
|
||||
{
|
||||
mAuthOK = message.getValueBoolean("ok");
|
||||
|
|
@ -375,7 +422,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
|
|||
versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION;
|
||||
message.setValueLLSD("versions", versions);
|
||||
|
||||
std::string plugin_version = "CEF plugin 1.1.3";
|
||||
std::string plugin_version = "CEF plugin 1.1.412";
|
||||
message.setValue("plugin_version", plugin_version);
|
||||
sendMessage(message);
|
||||
}
|
||||
|
|
@ -441,17 +488,17 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
|
|||
mCEFLib->setOnTitleChangeCallback(std::bind(&MediaPluginCEF::onTitleChangeCallback, this, std::placeholders::_1));
|
||||
mCEFLib->setOnLoadStartCallback(std::bind(&MediaPluginCEF::onLoadStartCallback, this));
|
||||
mCEFLib->setOnLoadEndCallback(std::bind(&MediaPluginCEF::onLoadEndCallback, this, std::placeholders::_1));
|
||||
mCEFLib->setOnLoadErrorCallback(std::bind(&MediaPluginCEF::onLoadError, this, std::placeholders::_1, std::placeholders::_2));
|
||||
mCEFLib->setOnAddressChangeCallback(std::bind(&MediaPluginCEF::onAddressChangeCallback, this, std::placeholders::_1));
|
||||
mCEFLib->setOnNavigateURLCallback(std::bind(&MediaPluginCEF::onNavigateURLCallback, this, std::placeholders::_1, std::placeholders::_2));
|
||||
mCEFLib->setOnOpenPopupCallback(std::bind(&MediaPluginCEF::onOpenPopupCallback, this, std::placeholders::_1, std::placeholders::_2));
|
||||
mCEFLib->setOnHTTPAuthCallback(std::bind(&MediaPluginCEF::onHTTPAuthCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
|
||||
mCEFLib->setOnFileDownloadCallback(std::bind(&MediaPluginCEF::onFileDownloadCallback, this, std::placeholders::_1));
|
||||
mCEFLib->setOnFileDialogCallback(std::bind(&MediaPluginCEF::onFileDialogCallback, this));
|
||||
mCEFLib->setOnFileDialogCallback(std::bind(&MediaPluginCEF::onFileDialog, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
|
||||
mCEFLib->setOnCursorChangedCallback(std::bind(&MediaPluginCEF::onCursorChangedCallback, this, std::placeholders::_1));
|
||||
mCEFLib->setOnRequestExitCallback(std::bind(&MediaPluginCEF::onRequestExitCallback, this));
|
||||
|
||||
dullahan::dullahan_settings settings;
|
||||
settings.accept_language_list = mHostLanguage;
|
||||
settings.background_color = 0xffffffff;
|
||||
settings.background_color = 0xff282828;
|
||||
settings.cache_enabled = true;
|
||||
settings.cache_path = mCachePath;
|
||||
settings.cookie_store_path = mCookiePath;
|
||||
|
|
@ -470,6 +517,8 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
|
|||
settings.plugins_enabled = mPluginsEnabled;
|
||||
settings.user_agent_substring = mCEFLib->makeCompatibleUserAgentString(mUserAgentSubtring);
|
||||
settings.webgl_enabled = true;
|
||||
settings.log_file = mCefLogFile;
|
||||
settings.log_verbose = mCefLogVerbose;
|
||||
|
||||
std::vector<std::string> custom_schemes(1, "secondlife");
|
||||
mCEFLib->setCustomSchemes(custom_schemes);
|
||||
|
|
@ -499,8 +548,11 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
|
|||
{
|
||||
std::string user_data_path_cache = message_in.getValue("cache_path");
|
||||
std::string user_data_path_cookies = message_in.getValue("cookies_path");
|
||||
|
||||
mCachePath = user_data_path_cache + "cef_cache";
|
||||
mCookiePath = user_data_path_cookies + "cef_cookies";
|
||||
mCefLogFile = message_in.getValue("cef_log_file");
|
||||
mCefLogVerbose = message_in.getValueBoolean("cef_verbose_log");
|
||||
}
|
||||
else if (message_name == "size_change")
|
||||
{
|
||||
|
|
@ -522,11 +574,11 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
|
|||
|
||||
mTextureWidth = texture_width;
|
||||
mTextureHeight = texture_height;
|
||||
|
||||
mCEFLib->setSize(mWidth, mHeight);
|
||||
};
|
||||
};
|
||||
|
||||
mCEFLib->setSize(mWidth, mHeight);
|
||||
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response");
|
||||
message.setValue("name", name);
|
||||
message.setValueS32("width", width);
|
||||
|
|
@ -653,7 +705,14 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
|
|||
}
|
||||
if (message_name == "pick_file_response")
|
||||
{
|
||||
mPickedFile = message_in.getValue("file");
|
||||
LLSD file_list_llsd = message_in.getValueLLSD("file_list");
|
||||
|
||||
LLSD::array_const_iterator iter = file_list_llsd.beginArray();
|
||||
LLSD::array_const_iterator end = file_list_llsd.endArray();
|
||||
for (; iter != end; ++iter)
|
||||
{
|
||||
mPickedFiles.push_back(((*iter).asString()));
|
||||
}
|
||||
}
|
||||
if (message_name == "auth_response")
|
||||
{
|
||||
|
|
@ -700,6 +759,10 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
|
|||
{
|
||||
mCookiesEnabled = message_in.getValueBoolean("enable");
|
||||
}
|
||||
else if (message_name == "clear_cookies")
|
||||
{
|
||||
mCEFLib->deleteAllCookies();
|
||||
}
|
||||
else if (message_name == "set_user_agent")
|
||||
{
|
||||
mUserAgentSubtring = message_in.getValue("user_agent");
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
5.1.3
|
||||
5.1.4
|
||||
|
|
|
|||
|
|
@ -21042,6 +21042,17 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>CefVerboseLog</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Enable/disable CEF verbose loggingk</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSShowServerVersionChangeNotice</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
|
|
@ -2318,8 +2318,6 @@ bool LLAppViewer::cleanup()
|
|||
|
||||
LLAvatarIconIDCache::getInstance()->save();
|
||||
|
||||
LLViewerMedia::saveCookieFile();
|
||||
|
||||
// Stop the plugin read thread if it's running.
|
||||
LLPluginProcessParent::setUseReadThread(false);
|
||||
|
||||
|
|
@ -3832,8 +3830,14 @@ LLSD LLAppViewer::getViewerInfo() const
|
|||
cef_ver_codec << " / CEF: ";
|
||||
cef_ver_codec << CEF_VERSION;
|
||||
|
||||
cef_ver_codec << " / Chrome: ";
|
||||
cef_ver_codec << " / Chromium: ";
|
||||
cef_ver_codec << CHROME_VERSION_MAJOR;
|
||||
cef_ver_codec << ".";
|
||||
cef_ver_codec << CHROME_VERSION_MINOR;
|
||||
cef_ver_codec << ".";
|
||||
cef_ver_codec << CHROME_VERSION_BUILD;
|
||||
cef_ver_codec << ".";
|
||||
cef_ver_codec << CHROME_VERSION_PATCH;
|
||||
|
||||
info["LIBCEF_VERSION"] = cef_ver_codec.str();
|
||||
//#else
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/**
|
||||
* @file llfloaterfacebook.cpp
|
||||
* @brief Implementation of llfloaterfacebook
|
||||
* @author Gilbert@lindenlab.com
|
||||
|
|
@ -41,7 +41,6 @@
|
|||
#include "llresmgr.h" // LLLocale
|
||||
#include "llsdserialize.h"
|
||||
#include "llloadingindicator.h"
|
||||
#include "llplugincookiestore.h"
|
||||
#include "llslurl.h"
|
||||
#include "lltrans.h"
|
||||
#include "llsnapshotlivepreview.h"
|
||||
|
|
@ -303,16 +302,11 @@ void LLFacebookStatusPanel::showConnectedLayout()
|
|||
void LLFacebookStatusPanel::onConnect()
|
||||
{
|
||||
LLFacebookConnect::instance().checkConnectionToFacebook(true);
|
||||
|
||||
//Clear only the facebook browser cookies so that the facebook login screen appears
|
||||
LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com");
|
||||
}
|
||||
|
||||
void LLFacebookStatusPanel::onDisconnect()
|
||||
{
|
||||
LLFacebookConnect::instance().disconnectFromFacebook();
|
||||
|
||||
LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com");
|
||||
}
|
||||
|
||||
void LLFacebookStatusPanel::clearAndClose()
|
||||
|
|
@ -914,7 +908,7 @@ void LLFacebookCheckinPanel::sendCheckin()
|
|||
LLAgentUI::buildSLURL(slurl);
|
||||
std::string slurl_string = slurl.getSLURLString();
|
||||
|
||||
// Use a valid http:// URL if the scheme is secondlife://
|
||||
// Use a valid http:// URL if the scheme is secondlife://
|
||||
LLURI slurl_uri(slurl_string);
|
||||
if (slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@
|
|||
#include "llresmgr.h" // LLLocale
|
||||
#include "llsdserialize.h"
|
||||
#include "llloadingindicator.h"
|
||||
#include "llplugincookiestore.h"
|
||||
#include "llslurl.h"
|
||||
#include "lltrans.h"
|
||||
#include "llsnapshotlivepreview.h"
|
||||
|
|
@ -889,16 +888,11 @@ void LLFlickrAccountPanel::showConnectedLayout()
|
|||
void LLFlickrAccountPanel::onConnect()
|
||||
{
|
||||
LLFlickrConnect::instance().checkConnectionToFlickr(true);
|
||||
|
||||
//Clear only the flickr browser cookies so that the flickr login screen appears
|
||||
LLViewerMedia::getCookieStore()->removeCookiesByDomain(".flickr.com");
|
||||
}
|
||||
|
||||
void LLFlickrAccountPanel::onDisconnect()
|
||||
{
|
||||
LLFlickrConnect::instance().disconnectFromFlickr();
|
||||
|
||||
LLViewerMedia::getCookieStore()->removeCookiesByDomain(".flickr.com");
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
|
|
|
|||
|
|
@ -560,7 +560,6 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
|
|||
mCommitCallbackRegistrar.add("Pref.BrowseCrashLogs", boost::bind(&LLFloaterPreference::onClickBrowseCrashLogs, this));
|
||||
mCommitCallbackRegistrar.add("Pref.BrowseSettingsDir", boost::bind(&LLFloaterPreference::onClickBrowseSettingsDir, this));
|
||||
mCommitCallbackRegistrar.add("Pref.BrowseLogPath", boost::bind(&LLFloaterPreference::onClickBrowseChatLogDir, this));
|
||||
mCommitCallbackRegistrar.add("Pref.Cookies", boost::bind(&LLFloaterPreference::onClickCookies, this));
|
||||
mCommitCallbackRegistrar.add("Pref.Javascript", boost::bind(&LLFloaterPreference::onClickJavascript, this));
|
||||
//[FIX FIRE-2765 : SJ] Making sure Reset button resets works
|
||||
mCommitCallbackRegistrar.add("Pref.ResetLogPath", boost::bind(&LLFloaterPreference::onClickResetLogPath, this));
|
||||
|
|
@ -1849,16 +1848,13 @@ void LLFloaterPreference::setPreprocInclude()
|
|||
}
|
||||
}
|
||||
|
||||
//[FIX JIRA-1971 : SJ] Show an notify when Cookies setting change
|
||||
void LLFloaterPreference::onClickCookies()
|
||||
{
|
||||
LLNotificationsUtil::add("DisableCookiesBreaksSearch");
|
||||
}
|
||||
|
||||
//[FIX JIRA-1971 : SJ] Show an notify when Javascript setting change
|
||||
void LLFloaterPreference::onClickJavascript()
|
||||
{
|
||||
LLNotificationsUtil::add("DisableJavascriptBreaksSearch");
|
||||
if (!gSavedSettings.getBOOL("BrowserJavascriptEnabled"))
|
||||
{
|
||||
LLNotificationsUtil::add("DisableJavascriptBreaksSearch");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -184,7 +184,6 @@ public:
|
|||
void onClickBrowseChatLogDir();
|
||||
void onClickResetCache();
|
||||
void onClickClearCache(); // AO: was protected, moved to public
|
||||
void onClickCookies();
|
||||
void onClickJavascript();
|
||||
void onClickBrowseSettingsDir();
|
||||
void onClickSkin(LLUICtrl* ctrl,const LLSD& userdata);
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@
|
|||
#include "llresmgr.h" // LLLocale
|
||||
#include "llsdserialize.h"
|
||||
#include "llloadingindicator.h"
|
||||
#include "llplugincookiestore.h"
|
||||
#include "llslurl.h"
|
||||
#include "lltrans.h"
|
||||
#include "llsnapshotlivepreview.h"
|
||||
|
|
@ -782,16 +781,11 @@ void LLTwitterAccountPanel::showConnectedLayout()
|
|||
void LLTwitterAccountPanel::onConnect()
|
||||
{
|
||||
LLTwitterConnect::instance().checkConnectionToTwitter(true);
|
||||
|
||||
//Clear only the twitter browser cookies so that the twitter login screen appears
|
||||
LLViewerMedia::getCookieStore()->removeCookiesByDomain(".twitter.com");
|
||||
}
|
||||
|
||||
void LLTwitterAccountPanel::onDisconnect()
|
||||
{
|
||||
LLTwitterConnect::instance().disconnectFromTwitter();
|
||||
|
||||
LLViewerMedia::getCookieStore()->removeCookiesByDomain(".twitter.com");
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
|
|
|
|||
|
|
@ -1060,7 +1060,7 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
|
|||
// try as slurl first
|
||||
if (!LLURLDispatcher::dispatch(url, "clicked", NULL, mTrusted))
|
||||
{
|
||||
LLWeb::loadURL(url, target, std::string());
|
||||
LLWeb::loadURL(url, target, uuid);
|
||||
}
|
||||
|
||||
// CP: removing this code because we no longer support popups so this breaks the flow.
|
||||
|
|
|
|||
|
|
@ -1090,7 +1090,7 @@ void LLPanelMainInventory::updateItemcountText()
|
|||
}
|
||||
|
||||
mCounterCtrl->setValue(text);
|
||||
mCounterCtrl->setToolTip(text);
|
||||
//mCounterCtrl->setToolTip(text); // <FS:Ansariel> Include folders in inventory count
|
||||
}
|
||||
|
||||
void LLPanelMainInventory::onFocusReceived()
|
||||
|
|
|
|||
|
|
@ -1517,9 +1517,6 @@ bool idle_startup()
|
|||
// Load Avatars icons cache
|
||||
LLAvatarIconIDCache::getInstance()->load();
|
||||
|
||||
// Load media plugin cookies
|
||||
LLViewerMedia::loadCookieFile();
|
||||
|
||||
// <FS:Ansariel> [FS Persisted Avatar Render Settings]
|
||||
//LLRenderMuteList::getInstance()->loadFromFile();
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@
|
|||
#include "llpanelprofile.h"
|
||||
#include "llparcel.h"
|
||||
#include "llpluginclassmedia.h"
|
||||
#include "llplugincookiestore.h"
|
||||
#include "llurldispatcher.h"
|
||||
#include "lluuid.h"
|
||||
#include "llversioninfo.h"
|
||||
|
|
@ -154,7 +153,6 @@ LLViewerMediaObserver::~LLViewerMediaObserver()
|
|||
}
|
||||
|
||||
|
||||
LLPluginCookieStore *LLViewerMedia::sCookieStore = NULL;
|
||||
LLURL LLViewerMedia::sOpenIDURL;
|
||||
std::string LLViewerMedia::sOpenIDCookie;
|
||||
LLPluginClassMedia* LLViewerMedia::sSpareBrowserMediaSource = NULL;
|
||||
|
|
@ -169,8 +167,6 @@ static F64 sLowestLoadableImplInterest = 0.0f;
|
|||
static bool sAnyMediaShowing = false;
|
||||
static bool sAnyMediaPlaying = false;
|
||||
static boost::signals2::connection sTeleportFinishConnection;
|
||||
static std::string sUpdatedCookies;
|
||||
static const char *PLUGIN_COOKIE_FILE_NAME = "plugin_cookies.txt";
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
static void add_media_impl(LLViewerMediaImpl* media)
|
||||
|
|
@ -614,12 +610,6 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
|
|||
|
||||
sAnyMediaShowing = false;
|
||||
sAnyMediaPlaying = false;
|
||||
sUpdatedCookies = getCookieStore()->getChangedCookies();
|
||||
if(!sUpdatedCookies.empty())
|
||||
{
|
||||
LL_DEBUGS() << "updated cookies will be sent to all loaded plugins: " << LL_ENDL;
|
||||
LL_DEBUGS() << sUpdatedCookies << LL_ENDL;
|
||||
}
|
||||
|
||||
impl_list::iterator iter = sViewerMediaImplList.begin();
|
||||
impl_list::iterator end = sViewerMediaImplList.end();
|
||||
|
|
@ -1087,64 +1077,6 @@ void LLViewerMedia::clearAllCookies()
|
|||
pimpl->mMediaSource->clear_cookies();
|
||||
}
|
||||
}
|
||||
|
||||
// Clear all cookies from the cookie store
|
||||
getCookieStore()->setAllCookies("");
|
||||
|
||||
// FIXME: this may not be sufficient, since the on-disk cookie file won't get written until some browser instance exits cleanly.
|
||||
// It also won't clear cookies for other accounts, or for any account if we're not logged in, and won't do anything at all if there are no webkit plugins loaded.
|
||||
// Until such time as we can centralize cookie storage, the following hack should cover these cases:
|
||||
|
||||
// HACK: Look for cookie files in all possible places and delete them.
|
||||
// NOTE: this assumes knowledge of what happens inside the webkit plugin (it's what adds 'browser_profile' to the path and names the cookie file)
|
||||
|
||||
// Places that cookie files can be:
|
||||
// <getOSUserAppDir>/browser_profile/cookies
|
||||
// <getOSUserAppDir>/first_last/browser_profile/cookies (note that there may be any number of these!)
|
||||
// <getOSUserAppDir>/first_last/plugin_cookies.txt (note that there may be any number of these!)
|
||||
|
||||
std::string base_dir = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter();
|
||||
std::string target;
|
||||
std::string filename;
|
||||
|
||||
LL_DEBUGS() << "base dir = " << base_dir << LL_ENDL;
|
||||
|
||||
// The non-logged-in version is easy
|
||||
target = base_dir;
|
||||
target += "browser_profile";
|
||||
target += gDirUtilp->getDirDelimiter();
|
||||
target += "cookies";
|
||||
LL_DEBUGS() << "target = " << target << LL_ENDL;
|
||||
if(LLFile::isfile(target))
|
||||
{
|
||||
LLFile::remove(target);
|
||||
}
|
||||
|
||||
// the hard part: iterate over all user directories and delete the cookie file from each one
|
||||
LLDirIterator dir_iter(base_dir, "*_*");
|
||||
while (dir_iter.next(filename))
|
||||
{
|
||||
target = gDirUtilp->add(base_dir, filename);
|
||||
gDirUtilp->append(target, "browser_profile");
|
||||
gDirUtilp->append(target, "cookies");
|
||||
LL_DEBUGS() << "target = " << target << LL_ENDL;
|
||||
if(LLFile::isfile(target))
|
||||
{
|
||||
LLFile::remove(target);
|
||||
}
|
||||
|
||||
// Other accounts may have new-style cookie files too -- delete them as well
|
||||
target = gDirUtilp->add(base_dir, filename);
|
||||
gDirUtilp->append(target, PLUGIN_COOKIE_FILE_NAME);
|
||||
LL_DEBUGS() << "target = " << target << LL_ENDL;
|
||||
if(LLFile::isfile(target))
|
||||
{
|
||||
LLFile::remove(target);
|
||||
}
|
||||
}
|
||||
|
||||
// If we have an OpenID cookie, re-add it to the cookie store.
|
||||
setOpenIDCookie(std::string());
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -1173,7 +1105,7 @@ void LLViewerMedia::setCookiesEnabled(bool enabled)
|
|||
LLViewerMediaImpl* pimpl = *iter;
|
||||
if(pimpl->mMediaSource)
|
||||
{
|
||||
pimpl->mMediaSource->enable_cookies(enabled);
|
||||
pimpl->mMediaSource->cookies_enabled(enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1198,127 +1130,7 @@ void LLViewerMedia::setProxyConfig(bool enable, const std::string &host, int por
|
|||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// static
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// static
|
||||
LLPluginCookieStore *LLViewerMedia::getCookieStore()
|
||||
{
|
||||
if(sCookieStore == NULL)
|
||||
{
|
||||
sCookieStore = new LLPluginCookieStore;
|
||||
}
|
||||
|
||||
return sCookieStore;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// static
|
||||
void LLViewerMedia::loadCookieFile()
|
||||
{
|
||||
// build filename for each user
|
||||
std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PLUGIN_COOKIE_FILE_NAME);
|
||||
|
||||
if (resolved_filename.empty())
|
||||
{
|
||||
LL_INFOS() << "can't get path to plugin cookie file - probably not logged in yet." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
// open the file for reading
|
||||
llifstream file(resolved_filename.c_str());
|
||||
if (!file.is_open())
|
||||
{
|
||||
LL_WARNS() << "can't load plugin cookies from file \"" << PLUGIN_COOKIE_FILE_NAME << "\"" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
getCookieStore()->readAllCookies(file, true);
|
||||
|
||||
file.close();
|
||||
|
||||
// send the clear_cookies message to all loaded plugins
|
||||
impl_list::iterator iter = sViewerMediaImplList.begin();
|
||||
impl_list::iterator end = sViewerMediaImplList.end();
|
||||
for (; iter != end; iter++)
|
||||
{
|
||||
LLViewerMediaImpl* pimpl = *iter;
|
||||
if(pimpl->mMediaSource)
|
||||
{
|
||||
pimpl->mMediaSource->clear_cookies();
|
||||
}
|
||||
}
|
||||
|
||||
// If we have an OpenID cookie, re-add it to the cookie store.
|
||||
setOpenIDCookie(std::string());
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// static
|
||||
void LLViewerMedia::saveCookieFile()
|
||||
{
|
||||
// build filename for each user
|
||||
std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PLUGIN_COOKIE_FILE_NAME);
|
||||
|
||||
if (resolved_filename.empty())
|
||||
{
|
||||
LL_INFOS() << "can't get path to plugin cookie file - probably not logged in yet." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
// open a file for writing
|
||||
llofstream file(resolved_filename.c_str());
|
||||
if (!file.is_open())
|
||||
{
|
||||
LL_WARNS() << "can't open plugin cookie file \"" << PLUGIN_COOKIE_FILE_NAME << "\" for writing" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
getCookieStore()->writePersistentCookies(file);
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// static
|
||||
void LLViewerMedia::addCookie(const std::string &name, const std::string &value, const std::string &domain, const LLDate &expires, const std::string &path, bool secure)
|
||||
{
|
||||
std::stringstream cookie;
|
||||
|
||||
cookie << name << "=" << LLPluginCookieStore::quoteString(value);
|
||||
|
||||
if(expires.notNull())
|
||||
{
|
||||
cookie << "; expires=" << expires.asRFC1123();
|
||||
}
|
||||
|
||||
cookie << "; domain=" << domain;
|
||||
|
||||
cookie << "; path=" << path;
|
||||
|
||||
if(secure)
|
||||
{
|
||||
cookie << "; secure";
|
||||
}
|
||||
|
||||
getCookieStore()->setCookies(cookie.str());
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// static
|
||||
void LLViewerMedia::addSessionCookie(const std::string &name, const std::string &value, const std::string &domain, const std::string &path, bool secure)
|
||||
{
|
||||
// A session cookie just has a NULL date.
|
||||
addCookie(name, value, domain, LLDate(), path, secure);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// static
|
||||
void LLViewerMedia::removeCookie(const std::string &name, const std::string &domain, const std::string &path )
|
||||
{
|
||||
// To remove a cookie, add one with the same name, domain, and path that expires in the past.
|
||||
|
||||
addCookie(name, "", domain, LLDate(LLDate::now().secondsSinceEpoch() - 1.0), path);
|
||||
}
|
||||
|
||||
//// static
|
||||
|
||||
LLSD LLViewerMedia::getHeaders()
|
||||
{
|
||||
|
|
@ -1423,8 +1235,6 @@ void LLViewerMedia::getOpenIDCookieCoro(std::string url)
|
|||
hostEnd = authority.size();
|
||||
}
|
||||
|
||||
getCookieStore()->setCookiesFromHost(sOpenIDCookie, authority.substr(hostStart, hostEnd - hostStart));
|
||||
|
||||
if (url.length())
|
||||
{
|
||||
LLMediaCtrl* media_instance = LLFloaterReg::getInstance("destinations")->getChild<LLMediaCtrl>("destination_guide_contents");
|
||||
|
|
@ -1462,7 +1272,6 @@ void LLViewerMedia::getOpenIDCookieCoro(std::string url)
|
|||
httpHeaders->append(HTTP_OUT_HEADER_COOKIE, sOpenIDCookie);
|
||||
httpHeaders->append(HTTP_OUT_HEADER_USER_AGENT, getCurrentUserAgent());
|
||||
|
||||
|
||||
LL_DEBUGS("MediaAuth") << "Requesting " << url << LL_ENDL;
|
||||
LL_DEBUGS("MediaAuth") << "sOpenIDCookie = [" << sOpenIDCookie << "]" << LL_ENDL;
|
||||
|
||||
|
|
@ -1487,13 +1296,9 @@ void LLViewerMedia::getOpenIDCookieCoro(std::string url)
|
|||
const std::string& cookie = resultHeaders[HTTP_IN_HEADER_SET_COOKIE].asStringRef();
|
||||
LL_DEBUGS("MediaAuth") << "cookie = " << cookie << LL_ENDL;
|
||||
|
||||
// *TODO: What about bad status codes? Does this destroy previous cookies?
|
||||
LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie, hostAuth);
|
||||
|
||||
// Set cookie for snapshot publishing.
|
||||
std::string authCookie = cookie.substr(0, cookie.find(";")); // strip path
|
||||
LLWebProfile::setAuthCookie(authCookie);
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -1688,12 +1493,6 @@ void LLViewerMedia::cleanupClass()
|
|||
delete sSpareBrowserMediaSource;
|
||||
sSpareBrowserMediaSource = NULL;
|
||||
}
|
||||
|
||||
if (sCookieStore != NULL)
|
||||
{
|
||||
delete sCookieStore;
|
||||
sCookieStore = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -1943,6 +1742,8 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
|
|||
std::string user_data_path_cookies = gDirUtilp->getOSUserAppDir();
|
||||
user_data_path_cookies += gDirUtilp->getDirDelimiter();
|
||||
|
||||
std::string user_data_path_cef_log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef_log.txt");
|
||||
|
||||
// Fix for EXT-5960 - make browser profile specific to user (cache, cookies etc.)
|
||||
// If the linden username returned is blank, that can only mean we are
|
||||
// at the login page displaying login Web page or Web browser test via Develop menu.
|
||||
|
|
@ -1951,7 +1752,6 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
|
|||
std::string linden_user_dir = gDirUtilp->getLindenUserDir();
|
||||
if ( ! linden_user_dir.empty() )
|
||||
{
|
||||
// gDirUtilp->getLindenUserDir() is whole path, not just Linden name
|
||||
user_data_path_cookies = linden_user_dir;
|
||||
user_data_path_cookies += gDirUtilp->getDirDelimiter();
|
||||
};
|
||||
|
|
@ -1972,13 +1772,13 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
|
|||
{
|
||||
media_source = new LLPluginClassMedia(owner);
|
||||
media_source->setSize(default_width, default_height);
|
||||
media_source->setUserDataPath(user_data_path_cache, user_data_path_cookies);
|
||||
media_source->setUserDataPath(user_data_path_cache, user_data_path_cookies, user_data_path_cef_log);
|
||||
media_source->setLanguageCode(LLUI::getLanguage());
|
||||
media_source->setZoomFactor(zoom_factor);
|
||||
|
||||
// collect 'cookies enabled' setting from prefs and send to embedded browser
|
||||
bool cookies_enabled = gSavedSettings.getBOOL( "CookiesEnabled" );
|
||||
media_source->enable_cookies( cookies_enabled || clean_browser);
|
||||
media_source->cookies_enabled( cookies_enabled || clean_browser);
|
||||
|
||||
// collect 'plugins enabled' setting from prefs and send to embedded browser
|
||||
bool plugins_enabled = gSavedSettings.getBOOL( "BrowserPluginsEnabled" );
|
||||
|
|
@ -2085,17 +1885,6 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
|
|||
media_source->clear_cache();
|
||||
}
|
||||
|
||||
// TODO: Only send cookies to plugins that need them
|
||||
// Ideally, the plugin should tell us whether it handles cookies or not -- either via the init response or through a separate message.
|
||||
// Due to the ordering of messages, it's possible we wouldn't get that information back in time to send cookies before sending a navigate message,
|
||||
// which could cause odd race conditions.
|
||||
std::string all_cookies = LLViewerMedia::getCookieStore()->getAllCookies();
|
||||
LL_DEBUGS() << "setting cookies: " << all_cookies << LL_ENDL;
|
||||
if(!all_cookies.empty())
|
||||
{
|
||||
media_source->set_cookies(all_cookies);
|
||||
}
|
||||
|
||||
mMediaSource = media_source;
|
||||
mMediaSource->setDeleteOK(false) ;
|
||||
updateVolume();
|
||||
|
|
@ -3055,14 +2844,10 @@ void LLViewerMediaImpl::update()
|
|||
updateVolume();
|
||||
|
||||
// TODO: this is updated every frame - is this bad?
|
||||
updateJavascriptObject();
|
||||
|
||||
// If we didn't just create the impl, it may need to get cookie updates.
|
||||
if(!sUpdatedCookies.empty())
|
||||
{
|
||||
// TODO: Only send cookies to plugins that need them
|
||||
mMediaSource->set_cookies(sUpdatedCookies);
|
||||
}
|
||||
// Removing this as part of the post viewer64 media update
|
||||
// Removed as not implemented in CEF embedded browser
|
||||
// See MAINT-8194 for a more fuller description
|
||||
// updateJavascriptObject();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -3555,22 +3340,40 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
|
|||
|
||||
case LLViewerMediaObserver::MEDIA_EVENT_PICK_FILE_REQUEST:
|
||||
{
|
||||
// Display a file picker
|
||||
std::string response;
|
||||
|
||||
LLFilePicker& picker = LLFilePicker::instance();
|
||||
if (!picker.getOpenFile(LLFilePicker::FFLOAD_ALL))
|
||||
std::vector<std::string> responses;
|
||||
|
||||
bool pick_multiple_files = plugin->getIsMultipleFilePick();
|
||||
if (pick_multiple_files == false)
|
||||
{
|
||||
// The user didn't pick a file -- the empty response string will indicate this.
|
||||
picker.getOpenFile(LLFilePicker::FFLOAD_ALL);
|
||||
|
||||
std::string filename = picker.getFirstFile();
|
||||
responses.push_back(filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (picker.getMultipleOpenFiles())
|
||||
{
|
||||
std::string filename = picker.getFirstFile();
|
||||
|
||||
response = picker.getFirstFile();
|
||||
responses.push_back(filename);
|
||||
|
||||
plugin->sendPickFileResponse(response);
|
||||
while (!filename.empty())
|
||||
{
|
||||
filename = picker.getNextFile();
|
||||
|
||||
if (!filename.empty())
|
||||
{
|
||||
responses.push_back(filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
plugin->sendPickFileResponse(responses);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LLViewerMediaObserver::MEDIA_EVENT_AUTH_REQUEST:
|
||||
{
|
||||
LLNotification::Params auth_request_params;
|
||||
|
|
@ -3638,13 +3441,6 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// virtual
|
||||
void LLViewerMediaImpl::handleCookieSet(LLPluginClassMedia* self, const std::string &cookie)
|
||||
{
|
||||
LLViewerMedia::getCookieStore()->setCookies(cookie);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// virtual
|
||||
void
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ class LLViewerMediaTexture;
|
|||
class LLMediaEntry;
|
||||
class LLVOVolume;
|
||||
class LLMimeDiscoveryResponder;
|
||||
class LLPluginCookieStore;
|
||||
|
||||
typedef LLPointer<LLViewerMediaImpl> viewer_media_t;
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -149,13 +148,6 @@ public:
|
|||
// Set the proxy config for all loaded plugins
|
||||
static void setProxyConfig(bool enable, const std::string &host, int port);
|
||||
|
||||
static LLPluginCookieStore *getCookieStore();
|
||||
static void loadCookieFile();
|
||||
static void saveCookieFile();
|
||||
static void addCookie(const std::string &name, const std::string &value, const std::string &domain, const LLDate &expires, const std::string &path = std::string("/"), bool secure = false );
|
||||
static void addSessionCookie(const std::string &name, const std::string &value, const std::string &domain, const std::string &path = std::string("/"), bool secure = false );
|
||||
static void removeCookie(const std::string &name, const std::string &domain, const std::string &path = std::string("/") );
|
||||
|
||||
static void openIDSetup(const std::string &openid_url, const std::string &openid_token);
|
||||
static void openIDCookieResponse(const std::string& url, const std::string &cookie);
|
||||
|
||||
|
|
@ -178,7 +170,6 @@ private:
|
|||
static void openIDSetupCoro(std::string openidUrl, std::string openidToken);
|
||||
static void getOpenIDCookieCoro(std::string url);
|
||||
|
||||
static LLPluginCookieStore *sCookieStore;
|
||||
static LLURL sOpenIDURL;
|
||||
static std::string sOpenIDCookie;
|
||||
static LLPluginClassMedia* sSpareBrowserMediaSource;
|
||||
|
|
@ -337,7 +328,6 @@ public:
|
|||
|
||||
// Inherited from LLPluginClassMediaOwner
|
||||
/*virtual*/ void handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent);
|
||||
/*virtual*/ void handleCookieSet(LLPluginClassMedia* self, const std::string &cookie);
|
||||
|
||||
// LLEditMenuHandler overrides
|
||||
/*virtual*/ void cut();
|
||||
|
|
|
|||
|
|
@ -2829,6 +2829,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
|
|||
gSkinnedObjectSimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
|
||||
gSkinnedObjectSimpleWaterProgram.mFeatures.hasObjectSkinning = true;
|
||||
gSkinnedObjectSimpleWaterProgram.mFeatures.disableTextureIndex = true;
|
||||
gSkinnedObjectSimpleWaterProgram.mFeatures.hasAlphaMask = true;
|
||||
gSkinnedObjectSimpleWaterProgram.mShaderFiles.clear();
|
||||
gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
|
||||
gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
// libs
|
||||
#include "llbufferstream.h"
|
||||
#include "llimagepng.h"
|
||||
#include "llplugincookiestore.h"
|
||||
|
||||
#include "llsdserialize.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -12,11 +12,6 @@
|
|||
</layout_panel>
|
||||
<layout_panel name="debug_controls">
|
||||
<button name="web_test_home_page" tool_tip="Webtests Homepage"/>
|
||||
<button name="VLC Plugin Test MPEG4" tool_tip="MPEG4-Videotest"/>
|
||||
<button name="VLC Plugin Test MKV" tool_tip="MKV-Videotest"/>
|
||||
<button name="VLC Plugin Test WebM" tool_tip="WebM-Videotest"/>
|
||||
<button name="VLC Plugin Test MP3" tool_tip="MP3-Audiotest"/>
|
||||
<button name="VLC Plugin Test FLV" tool_tip="FLV-Test"/>
|
||||
</layout_panel>
|
||||
<layout_panel name="external_controls">
|
||||
<text name="plugin_fail_text">
|
||||
|
|
|
|||
|
|
@ -597,6 +597,9 @@ Sind Sie sicher, dass Sie fortfahren wollen?
|
|||
<notification name="CacheWillClear">
|
||||
Der Cache wird nach einem Neustart von [APP_NAME] geleert.
|
||||
</notification>
|
||||
<notification name="DisableJavascriptBreaksSearch">
|
||||
Wenn Sie Javascript deaktivieren wird die Suchfunktion nicht korrekt funktionieren und Sie werden sie nicht benutzen können.
|
||||
</notification>
|
||||
<notification name="CacheWillBeMoved">
|
||||
Der Cache wird nach einem Neustart von [APP_NAME] verschoben.
|
||||
Hinweis: Der Cache wird dabei gelöscht/geleert.
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
Web-Browser:
|
||||
</text>
|
||||
<radio_group name="preferred_browser_behavior">
|
||||
<radio_item label="Meinen Browser (IE, Firefox, Safari) für alle Links verwenden" name="new_external" tool_tip="Standard Webbrowser des Systems verwenden, um die Hilfe, Weblinks usw. anzuzeigen. Bei Vollbildmodus nicht empfohlen."/>
|
||||
<radio_item label="Standard-Webbrowser des Systems für alle Links verwenden" name="new_external" tool_tip="Standard-Webbrowser des Systems verwenden, um die Hilfe, Weblinks usw. anzuzeigen. Bei Vollbildmodus nicht empfohlen."/>
|
||||
<radio_item label="Integrierten Browser nur für Second-Life-Links verwenden" name="new_internal" tool_tip="Integrierten Webbrowser verwenden, um die Hilfe, Weblinks usw. anzuzeigen. Dieser Browser öffnet als neues Fenster innerhalb von [APP_NAME]."/>
|
||||
<radio_item label="Integrierten Browser für alle Links verwenden" name="new_internal_all" tool_tip="Integrierten Webbrowser verwenden, um die Hilfe, Weblinks usw. anzuzeigen. Dieser Browser öffnet als neues Fenster innerhalb von [APP_NAME]."/>
|
||||
</radio_group>
|
||||
|
|
@ -38,7 +38,6 @@
|
|||
</combo_box>
|
||||
<button label="Webbrowser-Cache löschen" name="ClearWebBrowserCache" width="160"/>
|
||||
<check_box label="Plugins aktivieren" name="browser_plugins_enabled"/>
|
||||
<check_box label="Cookies annehmen" name="cookies_enabled"/>
|
||||
<check_box label="Javascript aktivieren" name="browser_javascript_enabled"/>
|
||||
<check_box label="Medienbrowser-Popups aktivieren" name="media_popup_enabled"/>
|
||||
<button label="Proxy-Einstellungen ändern" label_selected="Proxy-Einstellungen ändern" name="set_proxy"/>
|
||||
|
|
|
|||
|
|
@ -8,14 +8,14 @@
|
|||
help_topic="floater_about"
|
||||
save_rect="true"
|
||||
title="About [APP_NAME]"
|
||||
width="470">
|
||||
width="500">
|
||||
|
||||
<tab_container
|
||||
follows="all"
|
||||
top="20"
|
||||
left="7"
|
||||
height="572"
|
||||
width="456"
|
||||
width="486"
|
||||
name="about_tab"
|
||||
tab_position="top">
|
||||
<panel
|
||||
|
|
@ -46,7 +46,7 @@ http://www.firestormviewer.org
|
|||
max_length="65536"
|
||||
name="support_editor"
|
||||
top_pad="5"
|
||||
width="444"
|
||||
width="474"
|
||||
word_wrap="true" />
|
||||
<button
|
||||
follows="left|top"
|
||||
|
|
@ -69,7 +69,7 @@ http://www.firestormviewer.org
|
|||
left="4"
|
||||
name="linden_intro"
|
||||
top="16"
|
||||
width="444"
|
||||
width="474"
|
||||
wrap="true">
|
||||
Firestorm would not be possible without the decision from Linden Lab to make their Second Life viewer source code available.
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ with open source contributions from:
|
|||
max_length="65536"
|
||||
name="contrib_names"
|
||||
top_pad="5"
|
||||
width="446"
|
||||
width="476"
|
||||
word_wrap="true">
|
||||
Dummy Name replaced at run time
|
||||
</text_editor>
|
||||
|
|
@ -122,7 +122,7 @@ Dummy Name replaced at run time
|
|||
left="5"
|
||||
name="firestorm_intro"
|
||||
top="0"
|
||||
width="420"
|
||||
width="450"
|
||||
wrap="true">
|
||||
Firestorm is a community development project to improve the SecondLife(tm) Viewer experience. We package contributions from various community developers along with code from Linden Lab and ourselves to bring you a quality, feature-rich viewer experience backed up by a large volunteer support team. Firestorm is brought to you by The Phoenix Firestorm Project, Inc., a non-profit organization.
|
||||
|
||||
|
|
@ -138,7 +138,7 @@ The Firestorm Development Team:
|
|||
max_length="65536"
|
||||
name="firestorm_names"
|
||||
top_pad="4"
|
||||
width="420"
|
||||
width="450"
|
||||
wrap="true">
|
||||
Ansariel Hiller, ArminWeatherHax, Arrehn Oberlander, Beq Janus, Cinder Roxley, Holy Gavenkrantz, Jessica Lyon, Kadah Coba, Kitty Barnett, Liny Odell, LordGregGreg Back, Mobius Ryba, Nicky Dasmijn, PanteraPolnocy, Selo Jacobus, Tankmaster Finesmith, Techwolf Lupindo, Tonya Souther, Tozh Taurog, Vortex Saito, WoLf Loonie, Wolfspirit Magic and Zi Ree.
|
||||
</text>
|
||||
|
|
@ -149,7 +149,7 @@ Ansariel Hiller, ArminWeatherHax, Arrehn Oberlander, Beq Janus, Cinder Roxley, H
|
|||
left="5"
|
||||
name="fs_contrib_intro"
|
||||
top_pad="8"
|
||||
width="420"
|
||||
width="450"
|
||||
wrap="true">
|
||||
Additional code generously contributed to Firestorm by:
|
||||
</text>
|
||||
|
|
@ -163,7 +163,7 @@ Additional code generously contributed to Firestorm by:
|
|||
max_length="65536"
|
||||
name="fs_contrib_names"
|
||||
top_pad="4"
|
||||
width="420"
|
||||
width="450"
|
||||
wrap="true">
|
||||
Albatroz Hird, Alexie Birman, Andromeda Rage, Armin Weatherwax, Beq Janus, Casper Warden, Chalice Yao, Cron Stardust, Damian Zhaoying, Dan Threebeards, Dawa Gurbux, Drake Arconis, Felyza Wishbringer, f0rbidden, Fractured Crystal, Geenz Spad, Gibson Firehawk, Hitomi Tiponi, Inusaito Sayori, Katharine Berry, Kittin Ninetails, Kool Koolhoven, Lance Corrimal, Latif Khalifa, Magne Metaverse LLC, Magus Freston, Manami Hokkigai, MartinRJ Fayray, McCabe Maxstead, Melancholy Lemon, Melysmile, Mimika Oh, Mister Acacia, Mysty Saunders, Nagi Michinaga, Name Short, nhede Core, NiranV Dean, Nogardrevlis Lectar, Paladin Forzane, paperwork, Peyton Menges, programmtest, Qwerty Venom, Revolution Smythe, Sahkolihaa Contepomi, sal Kaligawa, Samm Florian, Satomi Ahn, Sei Lisa, Sempervirens Oddfellow, Shin Wasp, Shyotl Kuhr, Sione Lomu, Skills Hak, StarlightShining, Sunset Faulkes, Thickbrick Sleaford, Vaalith Jinn, Vincent Sylvester, Whirly Fizzle, Xenhat Liamano, Zwagoth Klaar and others.
|
||||
</text>
|
||||
|
|
@ -174,7 +174,7 @@ Albatroz Hird, Alexie Birman, Andromeda Rage, Armin Weatherwax, Beq Janus, Caspe
|
|||
left="5"
|
||||
name="fs_support_intro"
|
||||
top_pad="8"
|
||||
width="420"
|
||||
width="450"
|
||||
wrap="true">
|
||||
Special thanks to our Firestorm Support Team, wiki editors, educators, and translators:
|
||||
</text>
|
||||
|
|
@ -188,7 +188,7 @@ Special thanks to our Firestorm Support Team, wiki editors, educators, and trans
|
|||
max_length="65536"
|
||||
name="fs_trans_names"
|
||||
top_pad="4"
|
||||
width="420"
|
||||
width="450"
|
||||
word_wrap="true">
|
||||
Afrika Burton, Albatroz Hird, Alexru Resident, alison Seesaw, AnaLucia Loon, Angell Airy, Annuccia Resident, Annuccia Vuckovic, Anubi Alter, Atthosz Amiot, Ayelin Ethaniel, Basement Desade, Bia Scribe, Bluezy Bleac, Clarke2, Christy Mansbridge, Chymy India, Cordoba Cluny, Damian Zhaoying, DARK Mirabella, Emmanuella Checchinato, Ed Merryman, Eressea Karsin, Erick Gregan, F0RBIDDEN, Fabry String, Fetish3d, Flandria Connolly, Foksy, Franklyn Watanabe, FreeSpirit Simmering, Gee McAuley, Greatfox Snowpaw, Gweneth Lange, Hatake Kohime, Hiroshi Kumaki, Hope Dreier, Jodi Nikolaidis, JogiTE Clip, Kool Koolhoven, Kosmox Voom, Lachrimo Skytower, Lalwende Leakey, Landaree Levee, Lassie, Lette Ponnier, Lina Pussycat, Lyn Mimistrobell, Marianne Qunhua, Marybeth Oceanlane, Mel Hinarada, Mickeala Praga, Miller Thor, Miro Collas, Mister Acacia, Morgause Whiteberry, Mysty Saunders, Nano Bouscario, narcisssia McMahon, Natem Andel, Nicoletta Schnute, Nisa Maverick, NogarDrevlis Lectar, Norton Burns, PanteraPolnocy, Peewee Musytari, Pisano Smit, PixelProphet Lane, Pol Xaron, Poledra Behemoth, Programmtest, Rander Teskat, Ricky Munz, Riku Highfield, RINOBIT Footman, Robert0 Siamendes, Roth Grut, Sabah Back, SaHaRa Connor, Selene Gregoire, Selo Jacobus, silvanaf Demina, Sniper Siemans, Spartaco Zemenis, Spino Forcella, Srilania Svoboda, Sunset Faulkes, Tanja Levenque, TankMaster Finesmith, Tarlyn Dagger, Thea Brianna, Toy Wylie, Whirly Fizzle, Willow Wilder, Wolfspirit Magic and XLR8RRICK Hudson.
|
||||
</text>
|
||||
|
|
@ -199,7 +199,7 @@ Afrika Burton, Albatroz Hird, Alexru Resident, alison Seesaw, AnaLucia Loon, Ang
|
|||
left="5"
|
||||
name="fs_art_intro"
|
||||
top_pad="8"
|
||||
width="420"
|
||||
width="450"
|
||||
wrap="true">
|
||||
Firestorm includes Starlight, modified for Firestorm. It is provided by residents for residents, with the intention of providing an alternative, brighter, and hopefully easier to use interface. For further details see <nolink>https://wiki.secondlife.com/wiki/Viewer_Skins/Starlight</nolink>.
|
||||
|
||||
|
|
@ -215,7 +215,7 @@ UI Artists and Designers:
|
|||
max_length="65536"
|
||||
name="fs_artists_names"
|
||||
top_pad="4"
|
||||
width="420"
|
||||
width="450"
|
||||
wrap="true">
|
||||
Adam Frisby, Alexandrea Fride, DarkAgent Baphomet, David Rowe, Digital Scribe, Hitomi Tiponi, Hugh Helendale, KirstenLee Cinquetti, Mobius Ryba, Nadin, Naomah Beaumont, Paladin Forzane, psi Merlin, samm florian, Sammie Benoir, Tommi Waydelich and Vincent Nacon.
|
||||
</text>
|
||||
|
|
@ -237,7 +237,7 @@ Adam Frisby, Alexandrea Fride, DarkAgent Baphomet, David Rowe, Digital Scribe, H
|
|||
max_length="65536"
|
||||
name="licenses_editor"
|
||||
top="16"
|
||||
width="444"
|
||||
width="474"
|
||||
word_wrap="true">
|
||||
3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion
|
||||
APR Copyright (C) 2011 The Apache Software Foundation
|
||||
|
|
|
|||
|
|
@ -180,108 +180,7 @@
|
|||
width="22">
|
||||
<button.commit_callback
|
||||
function="WebContent.TestURL"
|
||||
parameter="https://callum-linden.s3.amazonaws.com/ceftests.html"/>
|
||||
</button>
|
||||
|
||||
<button
|
||||
image_overlay="Video_URL_Off"
|
||||
image_disabled="PushButton_Disabled"
|
||||
image_disabled_selected="PushButton_Disabled"
|
||||
image_selected="PushButton_Selected"
|
||||
image_unselected="PushButton_Off"
|
||||
chrome="true"
|
||||
tool_tip="MPEG4 Video Test"
|
||||
enabled="true"
|
||||
follows="left|top"
|
||||
height="22"
|
||||
layout="topleft"
|
||||
left="27"
|
||||
name="VLC Plugin Test MPEG4"
|
||||
top="0"
|
||||
width="22">
|
||||
<button.commit_callback
|
||||
function="WebContent.TestURL"
|
||||
parameter="https://callum-linden.s3.amazonaws.com/sample_media/ss.mp4"/>
|
||||
</button>
|
||||
<button
|
||||
image_overlay="Video_URL_Off"
|
||||
image_disabled="PushButton_Disabled"
|
||||
image_disabled_selected="PushButton_Disabled"
|
||||
image_selected="PushButton_Selected"
|
||||
image_unselected="PushButton_Off"
|
||||
chrome="true"
|
||||
tool_tip="MKV Video Test"
|
||||
enabled="true"
|
||||
follows="left|top"
|
||||
height="22"
|
||||
layout="topleft"
|
||||
left="51"
|
||||
name="VLC Plugin Test MKV"
|
||||
top="0"
|
||||
width="22">
|
||||
<button.commit_callback
|
||||
function="WebContent.TestURL"
|
||||
parameter="https://callum-linden.s3.amazonaws.com/sample_media/jellyfish.mkv"/>
|
||||
</button>
|
||||
<button
|
||||
image_overlay="Video_URL_Off"
|
||||
image_disabled="PushButton_Disabled"
|
||||
image_disabled_selected="PushButton_Disabled"
|
||||
image_selected="PushButton_Selected"
|
||||
image_unselected="PushButton_Off"
|
||||
chrome="true"
|
||||
tool_tip="WebM Video Test"
|
||||
enabled="true"
|
||||
follows="left|top"
|
||||
height="22"
|
||||
layout="topleft"
|
||||
left="75"
|
||||
name="VLC Plugin Test WebM"
|
||||
top="0"
|
||||
width="22">
|
||||
<button.commit_callback
|
||||
function="WebContent.TestURL"
|
||||
parameter="https://callum-linden.s3.amazonaws.com/sample_media/jumprope.webm"/>
|
||||
</button>
|
||||
<button
|
||||
image_overlay="Video_URL_Off"
|
||||
image_disabled="PushButton_Disabled"
|
||||
image_disabled_selected="PushButton_Disabled"
|
||||
image_selected="PushButton_Selected"
|
||||
image_unselected="PushButton_Off"
|
||||
chrome="true"
|
||||
tool_tip="MP3 audio Test"
|
||||
enabled="true"
|
||||
follows="left|top"
|
||||
height="22"
|
||||
layout="topleft"
|
||||
left="99"
|
||||
name="VLC Plugin Test MP3"
|
||||
top="0"
|
||||
width="22">
|
||||
<button.commit_callback
|
||||
function="WebContent.TestURL"
|
||||
parameter="https://callum-linden.s3.amazonaws.com/alegria.mp3"/>
|
||||
</button>
|
||||
<button
|
||||
image_overlay="Video_URL_Off"
|
||||
image_disabled="PushButton_Disabled"
|
||||
image_disabled_selected="PushButton_Disabled"
|
||||
image_selected="PushButton_Selected"
|
||||
image_unselected="PushButton_Off"
|
||||
chrome="true"
|
||||
tool_tip="FLV Test"
|
||||
enabled="true"
|
||||
follows="left|top"
|
||||
height="22"
|
||||
layout="topleft"
|
||||
left="123"
|
||||
name="VLC Plugin Test FLV"
|
||||
top="0"
|
||||
width="22">
|
||||
<button.commit_callback
|
||||
function="WebContent.TestURL"
|
||||
parameter="https://callum-linden.s3.amazonaws.com/sample_media/vandal.flv"/>
|
||||
parameter="https://sl-viewer-media-system.s3.amazonaws.com/index.html"/>
|
||||
</button>
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
|
|
|
|||
|
|
@ -281,7 +281,7 @@
|
|||
name="Media Browser">
|
||||
<menu_item_call.on_click
|
||||
function="Advanced.WebContentTest"
|
||||
parameter="http://google.com"/>
|
||||
parameter="http://duckduckgo.com"/>
|
||||
</menu_item_call>
|
||||
<menu
|
||||
create_jump_keys="true"
|
||||
|
|
|
|||
|
|
@ -4283,7 +4283,7 @@
|
|||
shortcut="control|shift|Z">
|
||||
<menu_item_call.on_click
|
||||
function="Advanced.WebContentTest"
|
||||
parameter="http://google.com"/>
|
||||
parameter="http://duckduckgo.com"/>
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="FB Connect Test"
|
||||
|
|
|
|||
|
|
@ -1541,13 +1541,6 @@ Cache will be cleared after restarting [APP_NAME].
|
|||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="DisableCookiesBreaksSearch"
|
||||
type="alertmodal">
|
||||
If you disable cookies, the search function will not work properly, and you will not be able to use it.
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="DisableJavascriptBreaksSearch"
|
||||
type="alertmodal">
|
||||
If you disable Javascript, the search function will not work properly, and you will not be able to use it.
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@
|
|||
follows="left|top"
|
||||
height="23"
|
||||
label="Clear History"
|
||||
tool_tip="Clear login image, last location, teleport history, web, and texture cache"
|
||||
tool_tip="Clear login image, last location, teleport history, web and texture cache"
|
||||
layout="topleft"
|
||||
left="15"
|
||||
name="clear_cache"
|
||||
|
|
|
|||
|
|
@ -215,7 +215,6 @@
|
|||
width="400">
|
||||
Web browser:
|
||||
</text>
|
||||
|
||||
<radio_group
|
||||
control_name="PreferredBrowserBehavior"
|
||||
follows="left|top"
|
||||
|
|
@ -227,7 +226,7 @@
|
|||
width="480">
|
||||
<radio_item
|
||||
height="20"
|
||||
label="Use my browser (Chrome, Firefox, IE) for all links"
|
||||
label="Use the default system browser for all links"
|
||||
layout="topleft"
|
||||
left="0"
|
||||
name="new_external"
|
||||
|
|
@ -237,18 +236,18 @@
|
|||
width="480" />
|
||||
<radio_item
|
||||
height="20"
|
||||
label="Use built-in browser for Second Life links only"
|
||||
label="Use the built-in browser for Second Life links only"
|
||||
layout="topleft"
|
||||
left_delta="0"
|
||||
name="new_internal"
|
||||
value="1"
|
||||
tool_tip="Use the default system web browser for help, web links, etc. Builtin browser will be used only for LindenLab/SecondLife links."
|
||||
tool_tip="Use the default system web browser for help, web links, etc. The built-in browser will be used only for LindenLab/SecondLife links."
|
||||
top_delta="15"
|
||||
width="480" />
|
||||
<radio_item
|
||||
top_delta="15"
|
||||
height="20"
|
||||
label="Use built-in browser for all links"
|
||||
label="Use the built-in browser for all links"
|
||||
layout="topleft"
|
||||
left="0"
|
||||
name="new_internal_all"
|
||||
|
|
@ -323,23 +322,6 @@
|
|||
width="200"
|
||||
top_pad="5"/>
|
||||
|
||||
<check_box
|
||||
enabled="true"
|
||||
follows="left|top"
|
||||
height="16"
|
||||
initial_value="true"
|
||||
control_name="CookiesEnabled"
|
||||
label="Accept cookies"
|
||||
left_delta="0"
|
||||
mouse_opaque="true"
|
||||
name="cookies_enabled"
|
||||
radio_style="false"
|
||||
width="200"
|
||||
top_pad="5">
|
||||
<check_box.commit_callback
|
||||
function="Pref.Cookies" />
|
||||
</check_box>
|
||||
|
||||
<check_box
|
||||
enabled="true"
|
||||
follows="left|top"
|
||||
|
|
|
|||
|
|
@ -542,9 +542,6 @@ No se reembolsarán las cuotas pagadas.
|
|||
<notification name="CacheWillClear">
|
||||
La caché se limpiará cuando reinicies [APP_NAME].
|
||||
</notification>
|
||||
<notification name="DisableCookiesBreaksSearch">
|
||||
Si desactivas las cookies, la función de búsqueda no funcionará correctamente y no podrás usarla.
|
||||
</notification>
|
||||
<notification name="DisableJavascriptBreaksSearch">
|
||||
Si desactivas Javascript, la función de búsqueda no funcionará correctamente y no podrás usarla.
|
||||
</notification>
|
||||
|
|
|
|||
|
|
@ -616,9 +616,6 @@ L$ が不足しているのでこのグループに参加することができ
|
|||
<notification name="CacheWillClear">
|
||||
[APP_NAME] を再起動後にキャッシュがクリアされます。
|
||||
</notification>
|
||||
<notification name="DisableCookiesBreaksSearch">
|
||||
クッキーを無効にすると、検索機能が正しく働かず、検索を使用できなくなります。
|
||||
</notification>
|
||||
<notification name="DisableJavascriptBreaksSearch">
|
||||
Javascript を無効にすると、検索機能が正しく働かず、検索を使用できなくなります。
|
||||
</notification>
|
||||
|
|
|
|||
|
|
@ -510,9 +510,6 @@ Czy na pewno chcesz kontynuować?
|
|||
<notification name="CacheWillClear">
|
||||
Bufor danych zostanie wyczyszczony po restarcie aplikacji [APP_NAME].
|
||||
</notification>
|
||||
<notification name="DisableCookiesBreaksSearch">
|
||||
Jeśli wyłączysz ciasteczka, to wyszukiwarka przestanie działać.
|
||||
</notification>
|
||||
<notification name="DisableJavascriptBreaksSearch">
|
||||
Jeśli wyłączysz Javascript, to wyszukiwarka przestanie działać.
|
||||
</notification>
|
||||
|
|
|
|||
|
|
@ -549,9 +549,6 @@
|
|||
<notification name="CacheWillClear">
|
||||
Кэш будет очищен после перезапуска [APP_NAME].
|
||||
</notification>
|
||||
<notification name="DisableCookiesBreaksSearch">
|
||||
Если вы отключите Cookies, функции поиска не будут работать должным образом и вы не сможете его использовать.
|
||||
</notification>
|
||||
<notification name="DisableJavascriptBreaksSearch">
|
||||
Если вы отключите Javascript, функции поиска не будут работать должным образом и вы не сможете его использовать.
|
||||
</notification>
|
||||
|
|
|
|||
Loading…
Reference in New Issue