Merge viewer-bugsplat
commit
8b6392c0aa
|
|
@ -3444,9 +3444,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>c543e73c35c605eaf509bc7651c11227</string>
|
||||
<string>e2bef561238448fe512146baa6dacabc</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/27348/219718/viewer_manager-2.0.521526-darwin64-521526.tar.bz2</string>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28859/240421/viewer_manager-2.0.522507-darwin64-522507.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -3480,9 +3480,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>fec612973e0d70f82da8c8f22a10c6f3</string>
|
||||
<string>75cdf1afc293423553b6d190ce422412</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/27349/219725/viewer_manager-2.0.521526-windows-521526.tar.bz2</string>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28858/240427/viewer_manager-2.0.522507-windows-522507.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -3493,7 +3493,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>source_type</key>
|
||||
<string>hg</string>
|
||||
<key>version</key>
|
||||
<string>2.0.521526</string>
|
||||
<string>2.0.522507</string>
|
||||
</map>
|
||||
<key>vlc-bin</key>
|
||||
<map>
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ if (WINDOWS)
|
|||
wldap32
|
||||
gdi32
|
||||
user32
|
||||
ole32
|
||||
dbghelp
|
||||
)
|
||||
else (WINDOWS)
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#if LL_WINDOWS
|
||||
#include "llwin32headerslean.h"
|
||||
#include <stdlib.h> // Windows errno
|
||||
#include <vector>
|
||||
#else
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
|
@ -134,8 +135,10 @@ int warnif(const std::string& desc, const std::string& filename, int rc, int acc
|
|||
{
|
||||
// Only do any of this stuff (before LL_ENDL) if it will be logged.
|
||||
LL_DEBUGS("LLFile") << empty;
|
||||
const char* TEMP = getenv("TEMP");
|
||||
if (! TEMP)
|
||||
// would be nice to use LLDir for this, but dependency goes the
|
||||
// wrong way
|
||||
const char* TEMP = LLFile::tmpdir();
|
||||
if (! (TEMP && *TEMP))
|
||||
{
|
||||
LL_CONT << "No $TEMP, not running 'handle'";
|
||||
}
|
||||
|
|
@ -385,17 +388,13 @@ const char *LLFile::tmpdir()
|
|||
#if LL_WINDOWS
|
||||
sep = '\\';
|
||||
|
||||
DWORD len = GetTempPathW(0, L"");
|
||||
llutf16string utf16path;
|
||||
utf16path.resize(len + 1);
|
||||
len = GetTempPathW(static_cast<DWORD>(utf16path.size()), &utf16path[0]);
|
||||
utf8path = utf16str_to_utf8str(utf16path);
|
||||
std::vector<wchar_t> utf16path(MAX_PATH + 1);
|
||||
GetTempPathW(utf16path.size(), &utf16path[0]);
|
||||
utf8path = ll_convert_wide_to_string(&utf16path[0]);
|
||||
#else
|
||||
sep = '/';
|
||||
|
||||
char *env = getenv("TMPDIR");
|
||||
|
||||
utf8path = env ? env : "/tmp/";
|
||||
utf8path = LLStringUtil::getenv("TMPDIR", "/tmp/");
|
||||
#endif
|
||||
if (utf8path[utf8path.size() - 1] != sep)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -111,6 +111,9 @@
|
|||
|
||||
#endif
|
||||
|
||||
// Although thread_local is now a standard storage class, we can't just
|
||||
// #define LL_THREAD_LOCAL as thread_local because the *usage* is different.
|
||||
// We'll have to take the time to change LL_THREAD_LOCAL declarations by hand.
|
||||
#if LL_WINDOWS
|
||||
# define LL_THREAD_LOCAL __declspec(thread)
|
||||
#else
|
||||
|
|
@ -187,6 +190,24 @@
|
|||
#define LL_DLLIMPORT
|
||||
#endif // LL_WINDOWS
|
||||
|
||||
#if ! defined(LL_WINDOWS)
|
||||
#define LL_WCHAR_T_NATIVE 1
|
||||
#else // LL_WINDOWS
|
||||
// https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros
|
||||
// _WCHAR_T_DEFINED is defined if wchar_t is provided at all.
|
||||
// Specifically, it has value 1 if wchar_t is an intrinsic type, else empty.
|
||||
// _NATIVE_WCHAR_T_DEFINED has value 1 if wchar_t is intrinsic, else undefined.
|
||||
// For years we have compiled with /Zc:wchar_t-, meaning that wchar_t is a
|
||||
// typedef for unsigned short (in stddef.h). Lore has it that one of our
|
||||
// proprietary binary-only libraries has traditionally been built that way and
|
||||
// therefore EVERYTHING ELSE requires it. Therefore, in a typical Linden
|
||||
// Windows build, _WCHAR_T_DEFINED is defined but empty, while
|
||||
// _NATIVE_WCHAR_T_DEFINED is undefined.
|
||||
# if defined(_NATIVE_WCHAR_T_DEFINED)
|
||||
# define LL_WCHAR_T_NATIVE 1
|
||||
# endif // _NATIVE_WCHAR_T_DEFINED
|
||||
#endif // LL_WINDOWS
|
||||
|
||||
#if LL_COMMON_LINK_SHARED
|
||||
// CMake automagically defines llcommon_EXPORTS only when building llcommon
|
||||
// sources, and only when llcommon is a shared library (i.e. when
|
||||
|
|
|
|||
|
|
@ -1205,30 +1205,9 @@ static LLProcess::Status interpret_status(int status)
|
|||
/// GetLastError()/FormatMessage() boilerplate
|
||||
static std::string WindowsErrorString(const std::string& operation)
|
||||
{
|
||||
int result = GetLastError();
|
||||
|
||||
LPTSTR error_str = 0;
|
||||
if (FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
result,
|
||||
0,
|
||||
(LPTSTR)&error_str,
|
||||
0,
|
||||
NULL)
|
||||
!= 0)
|
||||
{
|
||||
// convert from wide-char string to multi-byte string
|
||||
char message[256];
|
||||
wcstombs(message, error_str, sizeof(message));
|
||||
message[sizeof(message)-1] = 0;
|
||||
LocalFree(error_str);
|
||||
// convert to std::string to trim trailing whitespace
|
||||
std::string mbsstr(message);
|
||||
mbsstr.erase(mbsstr.find_last_not_of(" \t\r\n"));
|
||||
return STRINGIZE(operation << " failed (" << result << "): " << mbsstr);
|
||||
}
|
||||
return STRINGIZE(operation << " failed (" << result
|
||||
<< "), but FormatMessage() did not explain");
|
||||
auto result = GetLastError();
|
||||
return STRINGIZE(operation << " failed (" << result << "): "
|
||||
<< windows_message<std::string>(result));
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "llerror.h"
|
||||
#include "llfasttimer.h"
|
||||
#include "llsd.h"
|
||||
#include <vector>
|
||||
|
||||
#if LL_WINDOWS
|
||||
#include "llwin32headerslean.h"
|
||||
|
|
@ -744,6 +745,11 @@ namespace snprintf_hack
|
|||
}
|
||||
}
|
||||
|
||||
std::string ll_convert_wide_to_string(const wchar_t* in)
|
||||
{
|
||||
return ll_convert_wide_to_string(in, CP_UTF8);
|
||||
}
|
||||
|
||||
std::string ll_convert_wide_to_string(const wchar_t* in, unsigned int code_page)
|
||||
{
|
||||
std::string out;
|
||||
|
|
@ -781,7 +787,12 @@ std::string ll_convert_wide_to_string(const wchar_t* in, unsigned int code_page)
|
|||
return out;
|
||||
}
|
||||
|
||||
wchar_t* ll_convert_string_to_wide(const std::string& in, unsigned int code_page)
|
||||
std::wstring ll_convert_string_to_wide(const std::string& in)
|
||||
{
|
||||
return ll_convert_string_to_wide(in, CP_UTF8);
|
||||
}
|
||||
|
||||
std::wstring ll_convert_string_to_wide(const std::string& in, unsigned int code_page)
|
||||
{
|
||||
// From review:
|
||||
// We can preallocate a wide char buffer that is the same length (in wchar_t elements) as the utf8 input,
|
||||
|
|
@ -791,28 +802,148 @@ wchar_t* ll_convert_string_to_wide(const std::string& in, unsigned int code_page
|
|||
// but we *are* seeing string operations taking a bunch of time, especially when constructing widgets.
|
||||
// int output_str_len = MultiByteToWideChar(code_page, 0, in.c_str(), in.length(), NULL, 0);
|
||||
|
||||
// reserve place to NULL terminator
|
||||
int output_str_len = in.length();
|
||||
wchar_t* w_out = new wchar_t[output_str_len + 1];
|
||||
// reserve an output buffer that will be destroyed on exit, with a place
|
||||
// to put NULL terminator
|
||||
std::vector<wchar_t> w_out(in.length() + 1);
|
||||
|
||||
memset(w_out, 0, output_str_len + 1);
|
||||
int real_output_str_len = MultiByteToWideChar (code_page, 0, in.c_str(), in.length(), w_out, output_str_len);
|
||||
memset(&w_out[0], 0, w_out.size());
|
||||
int real_output_str_len = MultiByteToWideChar(code_page, 0, in.c_str(), in.length(),
|
||||
&w_out[0], w_out.size() - 1);
|
||||
|
||||
//looks like MultiByteToWideChar didn't add null terminator to converted string, see EXT-4858.
|
||||
w_out[real_output_str_len] = 0;
|
||||
|
||||
return w_out;
|
||||
// construct string<wchar_t> from our temporary output buffer
|
||||
return {&w_out[0]};
|
||||
}
|
||||
|
||||
LLWString ll_convert_wide_to_wstring(const std::wstring& in)
|
||||
{
|
||||
// This function, like its converse, is a placeholder, encapsulating a
|
||||
// guilty little hack: the only "official" way nat has found to convert
|
||||
// between std::wstring (16 bits on Windows) and LLWString (UTF-32) is
|
||||
// by using iconv, which we've avoided so far. It kinda sorta works to
|
||||
// just copy individual characters...
|
||||
// The point is that if/when we DO introduce some more official way to
|
||||
// perform such conversions, we should only have to call it here.
|
||||
return { in.begin(), in.end() };
|
||||
}
|
||||
|
||||
std::wstring ll_convert_wstring_to_wide(const LLWString& in)
|
||||
{
|
||||
// See comments in ll_convert_wide_to_wstring()
|
||||
return { in.begin(), in.end() };
|
||||
}
|
||||
|
||||
std::string ll_convert_string_to_utf8_string(const std::string& in)
|
||||
{
|
||||
wchar_t* w_mesg = ll_convert_string_to_wide(in, CP_ACP);
|
||||
std::string out_utf8(ll_convert_wide_to_string(w_mesg, CP_UTF8));
|
||||
delete[] w_mesg;
|
||||
auto w_mesg = ll_convert_string_to_wide(in, CP_ACP);
|
||||
std::string out_utf8(ll_convert_wide_to_string(w_mesg.c_str(), CP_UTF8));
|
||||
|
||||
return out_utf8;
|
||||
}
|
||||
#endif // LL_WINDOWS
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void HeapFree_deleter(void* ptr)
|
||||
{
|
||||
// instead of LocalFree(), per https://stackoverflow.com/a/31541205
|
||||
HeapFree(GetProcessHeap(), NULL, ptr);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
template<>
|
||||
std::wstring windows_message<std::wstring>(DWORD error)
|
||||
{
|
||||
// derived from https://stackoverflow.com/a/455533
|
||||
wchar_t* rawptr = nullptr;
|
||||
auto okay = FormatMessageW(
|
||||
// use system message tables for GetLastError() codes
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
// internally allocate buffer and return its pointer
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
// you cannot pass insertion parameters (thanks Gandalf)
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS |
|
||||
// ignore line breaks in message definition text
|
||||
FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
||||
NULL, // lpSource, unused with FORMAT_MESSAGE_FROM_SYSTEM
|
||||
error, // dwMessageId
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // dwLanguageId
|
||||
(LPWSTR)&rawptr, // lpBuffer: force-cast wchar_t** to wchar_t*
|
||||
0, // nSize, unused with FORMAT_MESSAGE_ALLOCATE_BUFFER
|
||||
NULL); // Arguments, unused
|
||||
|
||||
// make a unique_ptr from rawptr so it gets cleaned up properly
|
||||
std::unique_ptr<wchar_t, void(*)(void*)> bufferptr(rawptr, HeapFree_deleter);
|
||||
|
||||
if (okay && bufferptr)
|
||||
{
|
||||
// got the message, return it ('okay' is length in characters)
|
||||
return { bufferptr.get(), okay };
|
||||
}
|
||||
|
||||
// did not get the message, synthesize one
|
||||
auto format_message_error = GetLastError();
|
||||
std::wostringstream out;
|
||||
out << L"GetLastError() " << error << L" (FormatMessageW() failed with "
|
||||
<< format_message_error << L")";
|
||||
return out.str();
|
||||
}
|
||||
|
||||
boost::optional<std::wstring> llstring_getoptenv(const std::string& key)
|
||||
{
|
||||
auto wkey = ll_convert_string_to_wide(key);
|
||||
// Take a wild guess as to how big the buffer should be.
|
||||
std::vector<wchar_t> buffer(1024);
|
||||
auto n = GetEnvironmentVariableW(wkey.c_str(), &buffer[0], buffer.size());
|
||||
// If our initial guess was too short, n will indicate the size (in
|
||||
// wchar_t's) that buffer should have been, including the terminating nul.
|
||||
if (n > (buffer.size() - 1))
|
||||
{
|
||||
// make it big enough
|
||||
buffer.resize(n);
|
||||
// and try again
|
||||
n = GetEnvironmentVariableW(wkey.c_str(), &buffer[0], buffer.size());
|
||||
}
|
||||
// did that (ultimately) succeed?
|
||||
if (n)
|
||||
{
|
||||
// great, return populated boost::optional
|
||||
return boost::optional<std::wstring>(&buffer[0]);
|
||||
}
|
||||
|
||||
// not successful
|
||||
auto last_error = GetLastError();
|
||||
// Don't bother warning for NOT_FOUND; that's an expected case
|
||||
if (last_error != ERROR_ENVVAR_NOT_FOUND)
|
||||
{
|
||||
LL_WARNS() << "GetEnvironmentVariableW('" << key << "') failed: "
|
||||
<< windows_message<std::string>(last_error) << LL_ENDL;
|
||||
}
|
||||
// return empty boost::optional
|
||||
return {};
|
||||
}
|
||||
|
||||
#else // ! LL_WINDOWS
|
||||
|
||||
boost::optional<std::string> llstring_getoptenv(const std::string& key)
|
||||
{
|
||||
auto found = getenv(key.c_str());
|
||||
if (found)
|
||||
{
|
||||
// return populated boost::optional
|
||||
return boost::optional<std::string>(found);
|
||||
}
|
||||
else
|
||||
{
|
||||
// return empty boost::optional
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ! LL_WINDOWS
|
||||
|
||||
long LLStringOps::sPacificTimeOffset = 0;
|
||||
long LLStringOps::sLocalTimeOffset = 0;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#ifndef LL_LLSTRING_H
|
||||
#define LL_LLSTRING_H
|
||||
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
//#include <locale>
|
||||
|
|
@ -341,6 +342,19 @@ public:
|
|||
const string_type& string,
|
||||
const string_type& substr);
|
||||
|
||||
/**
|
||||
* get environment string value with proper Unicode handling
|
||||
* (key is always UTF-8)
|
||||
* detect absence by return value == dflt
|
||||
*/
|
||||
static string_type getenv(const std::string& key, const string_type& dflt="");
|
||||
/**
|
||||
* get optional environment string value with proper Unicode handling
|
||||
* (key is always UTF-8)
|
||||
* detect absence by (! return value)
|
||||
*/
|
||||
static boost::optional<string_type> getoptenv(const std::string& key);
|
||||
|
||||
static void addCRLF(string_type& string);
|
||||
static void removeCRLF(string_type& string);
|
||||
static void removeWindowsCR(string_type& string);
|
||||
|
|
@ -500,6 +514,37 @@ LL_COMMON_API bool iswindividual(llwchar elem);
|
|||
* Unicode support
|
||||
*/
|
||||
|
||||
/// generic conversion aliases
|
||||
template<typename TO, typename FROM, typename Enable=void>
|
||||
struct ll_convert_impl
|
||||
{
|
||||
// Don't even provide a generic implementation. We specialize for every
|
||||
// combination we do support.
|
||||
TO operator()(const FROM& in) const;
|
||||
};
|
||||
|
||||
// Use a function template to get the nice ll_convert<TO>(from_value) API.
|
||||
template<typename TO, typename FROM>
|
||||
TO ll_convert(const FROM& in)
|
||||
{
|
||||
return ll_convert_impl<TO, FROM>()(in);
|
||||
}
|
||||
|
||||
// degenerate case
|
||||
template<typename T>
|
||||
struct ll_convert_impl<T, T>
|
||||
{
|
||||
T operator()(const T& in) const { return in; }
|
||||
};
|
||||
|
||||
// specialize ll_convert_impl<TO, FROM> to return EXPR
|
||||
#define ll_convert_alias(TO, FROM, EXPR) \
|
||||
template<> \
|
||||
struct ll_convert_impl<TO, FROM> \
|
||||
{ \
|
||||
TO operator()(const FROM& in) const { return EXPR; } \
|
||||
}
|
||||
|
||||
// Make the incoming string a utf8 string. Replaces any unknown glyph
|
||||
// with the UNKNOWN_CHARACTER. Once any unknown glyph is found, the rest
|
||||
// of the data may not be recovered.
|
||||
|
|
@ -507,30 +552,88 @@ LL_COMMON_API std::string rawstr_to_utf8(const std::string& raw);
|
|||
|
||||
//
|
||||
// We should never use UTF16 except when communicating with Win32!
|
||||
// https://docs.microsoft.com/en-us/cpp/cpp/char-wchar-t-char16-t-char32-t
|
||||
// nat 2018-12-14: I consider the whole llutf16string thing a mistake, because
|
||||
// the Windows APIs we want to call are all defined in terms of wchar_t*
|
||||
// (or worse, LPCTSTR).
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/winprog/windows-data-types
|
||||
|
||||
// While there is no point coding for an ASCII-only world (! defined(UNICODE)),
|
||||
// use of U16 and llutf16string for Windows APIs locks in /Zc:wchar_t-. Going
|
||||
// forward, we should code in terms of wchar_t and std::wstring so as to
|
||||
// support either setting of /Zc:wchar_t.
|
||||
|
||||
// The first link above states that char can be used to hold ASCII or any
|
||||
// multi-byte character set, and distinguishes wchar_t (UTF-16LE), char16_t
|
||||
// (UTF-16) and char32_t (UTF-32). Nonetheless, within this code base:
|
||||
// * char and std::string always hold UTF-8 (of which ASCII is a subset). It
|
||||
// is a BUG if they are used to pass strings in any other multi-byte
|
||||
// encoding.
|
||||
// * wchar_t and std::wstring should be our interface to Windows wide-string
|
||||
// APIs, and therefore hold UTF-16LE.
|
||||
// * U16 and llutf16string are the previous but DEPRECATED UTF-16LE type. Do
|
||||
// not introduce new uses of U16 or llutf16string for string data.
|
||||
// * llwchar and LLWString hold UTF-32 strings.
|
||||
// * Do not introduce char16_t or std::u16string.
|
||||
// * Do not introduce char32_t or std::u32string.
|
||||
//
|
||||
// This typedef may or may not be identical to std::wstring, depending on
|
||||
// LL_WCHAR_T_NATIVE.
|
||||
typedef std::basic_string<U16> llutf16string;
|
||||
|
||||
#if ! defined(LL_WCHAR_T_NATIVE)
|
||||
// wchar_t is identical to U16, and std::wstring is identical to llutf16string.
|
||||
// Defining an ll_convert alias involving llutf16string would collide with the
|
||||
// comparable preferred alias involving std::wstring. (In this scenario, if
|
||||
// you pass llutf16string, it will engage the std::wstring specialization.)
|
||||
#define ll_convert_u16_alias(TO, FROM, EXPR) // nothing
|
||||
#else // defined(LL_WCHAR_T_NATIVE)
|
||||
// wchar_t is a distinct native type, so llutf16string is also a distinct
|
||||
// type, and there IS a point to converting separately to/from llutf16string.
|
||||
// (But why? Windows APIs are still defined in terms of wchar_t, and
|
||||
// in this scenario llutf16string won't work for them!)
|
||||
#define ll_convert_u16_alias(TO, FROM, EXPR) ll_convert_alias(TO, FROM, EXPR)
|
||||
|
||||
#if LL_WINDOWS
|
||||
// LL_WCHAR_T_NATIVE is defined on non-Windows systems because, in fact,
|
||||
// wchar_t is native. Everywhere but Windows, we use it for llwchar (see
|
||||
// stdtypes.h). That makes LLWString identical to std::wstring, so these
|
||||
// aliases for std::wstring would collide with those for LLWString. Only
|
||||
// define on Windows, where converting between std::wstring and llutf16string
|
||||
// means copying chars.
|
||||
ll_convert_alias(llutf16string, std::wstring, llutf16string(in.begin(), in.end()));
|
||||
ll_convert_alias(std::wstring, llutf16string, std::wstring(in.begin(), in.end()));
|
||||
#endif // LL_WINDOWS
|
||||
#endif // defined(LL_WCHAR_T_NATIVE)
|
||||
|
||||
LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len);
|
||||
LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str);
|
||||
ll_convert_u16_alias(LLWString, llutf16string, utf16str_to_wstring(in));
|
||||
|
||||
LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len);
|
||||
LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str);
|
||||
ll_convert_u16_alias(llutf16string, LLWString, wstring_to_utf16str(in));
|
||||
|
||||
LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str, S32 len);
|
||||
LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str );
|
||||
ll_convert_u16_alias(llutf16string, std::string, utf8str_to_utf16str(in));
|
||||
|
||||
LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str, S32 len);
|
||||
LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str);
|
||||
// Same function, better name. JC
|
||||
inline LLWString utf8string_to_wstring(const std::string& utf8_string) { return utf8str_to_wstring(utf8_string); }
|
||||
// best name of all
|
||||
ll_convert_alias(LLWString, std::string, utf8string_to_wstring(in));
|
||||
|
||||
//
|
||||
LL_COMMON_API S32 wchar_to_utf8chars(llwchar inchar, char* outchars);
|
||||
|
||||
LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str, S32 len);
|
||||
LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str);
|
||||
ll_convert_alias(std::string, LLWString, wstring_to_utf8str(in));
|
||||
LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str, S32 len);
|
||||
LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str);
|
||||
ll_convert_u16_alias(std::string, llutf16string, utf16str_to_utf8str(in));
|
||||
|
||||
#if LL_WINDOWS
|
||||
inline std::string wstring_to_utf8str(const llutf16string &utf16str) { return utf16str_to_utf8str(utf16str);}
|
||||
|
|
@ -644,22 +747,77 @@ using snprintf_hack::snprintf;
|
|||
* This replaces the unsafe W2A macro from ATL.
|
||||
*/
|
||||
LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in, unsigned int code_page);
|
||||
LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in); // default CP_UTF8
|
||||
inline std::string ll_convert_wide_to_string(const std::wstring& in, unsigned int code_page)
|
||||
{
|
||||
return ll_convert_wide_to_string(in.c_str(), code_page);
|
||||
}
|
||||
inline std::string ll_convert_wide_to_string(const std::wstring& in)
|
||||
{
|
||||
return ll_convert_wide_to_string(in.c_str());
|
||||
}
|
||||
ll_convert_alias(std::string, std::wstring, ll_convert_wide_to_string(in));
|
||||
|
||||
/**
|
||||
* Converts a string to wide string.
|
||||
*
|
||||
* It will allocate memory for result string with "new []". Don't forget to release it with "delete []".
|
||||
*/
|
||||
LL_COMMON_API wchar_t* ll_convert_string_to_wide(const std::string& in, unsigned int code_page);
|
||||
LL_COMMON_API std::wstring ll_convert_string_to_wide(const std::string& in,
|
||||
unsigned int code_page);
|
||||
LL_COMMON_API std::wstring ll_convert_string_to_wide(const std::string& in);
|
||||
// default CP_UTF8
|
||||
ll_convert_alias(std::wstring, std::string, ll_convert_string_to_wide(in));
|
||||
|
||||
/**
|
||||
* Converts incoming string into urf8 string
|
||||
* Convert a Windows wide string to our LLWString
|
||||
*/
|
||||
LL_COMMON_API LLWString ll_convert_wide_to_wstring(const std::wstring& in);
|
||||
ll_convert_alias(LLWString, std::wstring, ll_convert_wide_to_wstring(in));
|
||||
|
||||
/**
|
||||
* Convert LLWString to Windows wide string
|
||||
*/
|
||||
LL_COMMON_API std::wstring ll_convert_wstring_to_wide(const LLWString& in);
|
||||
ll_convert_alias(std::wstring, LLWString, ll_convert_wstring_to_wide(in));
|
||||
|
||||
/**
|
||||
* Converts incoming string into utf8 string
|
||||
*
|
||||
*/
|
||||
LL_COMMON_API std::string ll_convert_string_to_utf8_string(const std::string& in);
|
||||
|
||||
/// Get Windows message string for passed GetLastError() code
|
||||
// VS 2013 doesn't let us forward-declare this template, which is what we
|
||||
// started with, so the implementation could reference the specialization we
|
||||
// haven't yet declared. Somewhat weirdly, just stating the generic
|
||||
// implementation in terms of the specialization works, even in this order...
|
||||
|
||||
// the general case is just a conversion from the sole implementation
|
||||
// Microsoft says DWORD is a typedef for unsigned long
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/winprog/windows-data-types
|
||||
// so rather than drag windows.h into everybody's include space...
|
||||
template<typename STRING>
|
||||
STRING windows_message(unsigned long error)
|
||||
{
|
||||
return ll_convert<STRING>(windows_message<std::wstring>(error));
|
||||
}
|
||||
|
||||
/// There's only one real implementation
|
||||
template<>
|
||||
LL_COMMON_API std::wstring windows_message<std::wstring>(unsigned long error);
|
||||
|
||||
/// Get Windows message string, implicitly calling GetLastError()
|
||||
template<typename STRING>
|
||||
STRING windows_message() { return windows_message<STRING>(GetLastError()); }
|
||||
|
||||
//@}
|
||||
#endif // LL_WINDOWS
|
||||
|
||||
LL_COMMON_API boost::optional<std::wstring> llstring_getoptenv(const std::string& key);
|
||||
|
||||
#else // ! LL_WINDOWS
|
||||
|
||||
LL_COMMON_API boost::optional<std::string> llstring_getoptenv(const std::string& key);
|
||||
|
||||
#endif // ! LL_WINDOWS
|
||||
|
||||
/**
|
||||
* Many of the 'strip' and 'replace' methods of LLStringUtilBase need
|
||||
|
|
@ -1602,6 +1760,37 @@ bool LLStringUtilBase<T>::endsWith(
|
|||
return (idx == (string.size() - substr.size()));
|
||||
}
|
||||
|
||||
// static
|
||||
template<class T>
|
||||
auto LLStringUtilBase<T>::getoptenv(const std::string& key) -> boost::optional<string_type>
|
||||
{
|
||||
auto found(llstring_getoptenv(key));
|
||||
if (found)
|
||||
{
|
||||
// return populated boost::optional
|
||||
return { ll_convert<string_type>(*found) };
|
||||
}
|
||||
else
|
||||
{
|
||||
// empty boost::optional
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
template<class T>
|
||||
auto LLStringUtilBase<T>::getenv(const std::string& key, const string_type& dflt) -> string_type
|
||||
{
|
||||
auto found(getoptenv(key));
|
||||
if (found)
|
||||
{
|
||||
return *found;
|
||||
}
|
||||
else
|
||||
{
|
||||
return dflt;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
BOOL LLStringUtilBase<T>::convertToBOOL(const string_type& string, BOOL& value)
|
||||
|
|
|
|||
|
|
@ -37,7 +37,12 @@ typedef signed int S32;
|
|||
typedef unsigned int U32;
|
||||
|
||||
#if LL_WINDOWS
|
||||
// Windows wchar_t is 16-bit
|
||||
// https://docs.microsoft.com/en-us/cpp/build/reference/zc-wchar-t-wchar-t-is-native-type
|
||||
// https://docs.microsoft.com/en-us/cpp/cpp/fundamental-types-cpp
|
||||
// Windows wchar_t is 16-bit, whichever way /Zc:wchar_t is set. In effect,
|
||||
// Windows wchar_t is always a typedef, either for unsigned short or __wchar_t.
|
||||
// (__wchar_t, available either way, is Microsoft's native 2-byte wchar_t type.)
|
||||
// In any case, llwchar should be a UTF-32 type.
|
||||
typedef U32 llwchar;
|
||||
#else
|
||||
typedef wchar_t llwchar;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "wrapllerrs.h"
|
||||
#include "llevents.h"
|
||||
#include "llprocess.h"
|
||||
#include "llstring.h"
|
||||
#include "stringize.h"
|
||||
#include "StringVec.h"
|
||||
#include <functional>
|
||||
|
|
@ -198,14 +199,12 @@ namespace tut
|
|||
// basename.
|
||||
reader_module(LLProcess::basename(
|
||||
reader.getName().substr(0, reader.getName().length()-3))),
|
||||
pPYTHON(getenv("PYTHON")),
|
||||
PYTHON(pPYTHON? pPYTHON : "")
|
||||
PYTHON(LLStringUtil::getenv("PYTHON"))
|
||||
{
|
||||
ensure("Set PYTHON to interpreter pathname", pPYTHON);
|
||||
ensure("Set PYTHON to interpreter pathname", !PYTHON.empty());
|
||||
}
|
||||
NamedExtTempFile reader;
|
||||
const std::string reader_module;
|
||||
const char* pPYTHON;
|
||||
const std::string PYTHON;
|
||||
};
|
||||
typedef test_group<llleap_data> llleap_group;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "stringize.h"
|
||||
#include "llsdutil.h"
|
||||
#include "llevents.h"
|
||||
#include "llstring.h"
|
||||
#include "wrapllerrs.h"
|
||||
|
||||
#if defined(LL_WINDOWS)
|
||||
|
|
@ -142,8 +143,8 @@ struct PythonProcessLauncher
|
|||
mDesc(desc),
|
||||
mScript("py", script)
|
||||
{
|
||||
const char* PYTHON(getenv("PYTHON"));
|
||||
tut::ensure("Set $PYTHON to the Python interpreter", PYTHON);
|
||||
auto PYTHON(LLStringUtil::getenv("PYTHON"));
|
||||
tut::ensure("Set $PYTHON to the Python interpreter", !PYTHON.empty());
|
||||
|
||||
mParams.desc = desc + " script";
|
||||
mParams.executable = PYTHON;
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ typedef U32 uint32_t;
|
|||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include "llprocess.h"
|
||||
#include "llstring.h"
|
||||
#endif
|
||||
|
||||
#include "boost/range.hpp"
|
||||
|
|
@ -1705,8 +1706,8 @@ namespace tut
|
|||
template <typename CONTENT>
|
||||
void python(const std::string& desc, const CONTENT& script, int expect=0)
|
||||
{
|
||||
const char* PYTHON(getenv("PYTHON"));
|
||||
ensure("Set $PYTHON to the Python interpreter", PYTHON);
|
||||
auto PYTHON(LLStringUtil::getenv("PYTHON"));
|
||||
ensure("Set $PYTHON to the Python interpreter", !PYTHON.empty());
|
||||
|
||||
NamedTempFile scriptfile("py", script);
|
||||
|
||||
|
|
@ -1714,7 +1715,7 @@ namespace tut
|
|||
std::string q("\"");
|
||||
std::string qPYTHON(q + PYTHON + q);
|
||||
std::string qscript(q + scriptfile.getName() + q);
|
||||
int rc = _spawnl(_P_WAIT, PYTHON, qPYTHON.c_str(), qscript.c_str(), NULL);
|
||||
int rc = _spawnl(_P_WAIT, PYTHON.c_str(), qPYTHON.c_str(), qscript.c_str(), NULL);
|
||||
if (rc == -1)
|
||||
{
|
||||
char buffer[256];
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "llsd.h"
|
||||
#include "llhost.h"
|
||||
#include "llexception.h"
|
||||
#include "llstring.h"
|
||||
#include "stringize.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
|
@ -46,12 +47,7 @@ struct CommtestError: public LLException
|
|||
|
||||
static bool query_verbose()
|
||||
{
|
||||
const char* cbose = getenv("INTEGRATION_TEST_VERBOSE");
|
||||
if (! cbose)
|
||||
{
|
||||
cbose = "1";
|
||||
}
|
||||
std::string strbose(cbose);
|
||||
std::string strbose(LLStringUtil::getenv("INTEGRATION_TEST_VERBOSE", "1"));
|
||||
return (! (strbose == "0" || strbose == "off" ||
|
||||
strbose == "false" || strbose == "quiet"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "llpumpio.h"
|
||||
|
||||
#include "lliosocket.h"
|
||||
#include "llstring.h"
|
||||
#include "stringize.h"
|
||||
#include "llcleanup.h"
|
||||
|
||||
|
|
@ -50,13 +51,13 @@ namespace tut
|
|||
{
|
||||
public:
|
||||
HTTPClientTestData():
|
||||
PORT(getenv("PORT")),
|
||||
PORT(LLStringUtil::getenv("PORT")),
|
||||
// Turning NULL PORT into empty string doesn't make things work;
|
||||
// that's just to keep this initializer from blowing up. We test
|
||||
// PORT separately in the constructor body.
|
||||
local_server(STRINGIZE("http://127.0.0.1:" << (PORT? PORT : "") << "/"))
|
||||
local_server(STRINGIZE("http://127.0.0.1:" << PORT << "/"))
|
||||
{
|
||||
ensure("Set environment variable PORT to local test server port", PORT);
|
||||
ensure("Set environment variable PORT to local test server port", !PORT.empty());
|
||||
apr_pool_create(&mPool, NULL);
|
||||
LLCurl::initClass(false);
|
||||
mClientPump = new LLPumpIO(mPool);
|
||||
|
|
@ -87,7 +88,7 @@ namespace tut
|
|||
}
|
||||
}
|
||||
|
||||
const char* const PORT;
|
||||
const std::string PORT;
|
||||
const std::string local_server;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -44,6 +44,12 @@
|
|||
// Third party library includes
|
||||
#include <boost/tokenizer.hpp>
|
||||
|
||||
#if LL_WINDOWS
|
||||
#include <Shlobj.h>
|
||||
#include <Knownfolders.h>
|
||||
#include <Objbase.h>
|
||||
#endif // LL_WINDOWS
|
||||
|
||||
const S32 BOLD_OFFSET = 1;
|
||||
|
||||
// static class members
|
||||
|
|
@ -1156,33 +1162,24 @@ LLFontGL* LLFontGL::getFontDefault()
|
|||
// static
|
||||
std::string LLFontGL::getFontPathSystem()
|
||||
{
|
||||
std::string system_path;
|
||||
#if LL_DARWIN
|
||||
// HACK for Mac OS X
|
||||
return "/System/Library/Fonts/";
|
||||
|
||||
// Try to figure out where the system's font files are stored.
|
||||
char *system_root = NULL;
|
||||
#if LL_WINDOWS
|
||||
system_root = getenv("SystemRoot"); /* Flawfinder: ignore */
|
||||
if (!system_root)
|
||||
{
|
||||
LL_WARNS() << "SystemRoot not found, attempting to load fonts from default path." << LL_ENDL;
|
||||
}
|
||||
#elif LL_WINDOWS
|
||||
wchar_t *pwstr = NULL;
|
||||
HRESULT okay = SHGetKnownFolderPath(FOLDERID_Fonts, 0, NULL, &pwstr);
|
||||
if (SUCCEEDED(okay) && pwstr)
|
||||
{
|
||||
std::string fontpath(ll_convert_wide_to_string(pwstr));
|
||||
// SHGetKnownFolderPath() contract requires us to free pwstr
|
||||
CoTaskMemFree(pwstr);
|
||||
return fontpath;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (system_root)
|
||||
{
|
||||
system_path = llformat("%s/fonts/", system_root);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if LL_WINDOWS
|
||||
// HACK for windows 98/Me
|
||||
system_path = "/WINDOWS/FONTS/";
|
||||
#elif LL_DARWIN
|
||||
// HACK for Mac OS X
|
||||
system_path = "/System/Library/Fonts/";
|
||||
#endif
|
||||
}
|
||||
return system_path;
|
||||
LL_WARNS() << "Could not determine system fonts path" << LL_ENDL;
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "lldir_linux.h"
|
||||
#include "llerror.h"
|
||||
#include "llrand.h"
|
||||
#include "llstring.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -40,28 +41,24 @@ static std::string getCurrentUserHome(char* fallback)
|
|||
{
|
||||
const uid_t uid = getuid();
|
||||
struct passwd *pw;
|
||||
char *result_cstr = fallback;
|
||||
|
||||
|
||||
pw = getpwuid(uid);
|
||||
if ((pw != NULL) && (pw->pw_dir != NULL))
|
||||
{
|
||||
result_cstr = (char*) pw->pw_dir;
|
||||
return pw->pw_dir;
|
||||
}
|
||||
|
||||
LL_INFOS() << "Couldn't detect home directory from passwd - trying $HOME" << LL_ENDL;
|
||||
auto home_env = LLStringUtil::getoptenv("HOME");
|
||||
if (home_env)
|
||||
{
|
||||
return *home_env;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "Couldn't detect home directory from passwd - trying $HOME" << LL_ENDL;
|
||||
const char *const home_env = getenv("HOME"); /* Flawfinder: ignore */
|
||||
if (home_env)
|
||||
{
|
||||
result_cstr = (char*) home_env;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "Couldn't detect home directory! Falling back to " << fallback << LL_ENDL;
|
||||
}
|
||||
LL_WARNS() << "Couldn't detect home directory! Falling back to " << fallback << LL_ENDL;
|
||||
return fallback;
|
||||
}
|
||||
|
||||
return std::string(result_cstr);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -156,18 +153,18 @@ void LLDir_Linux::initAppDirs(const std::string &app_name,
|
|||
if (!app_read_only_data_dir.empty())
|
||||
{
|
||||
mAppRODataDir = app_read_only_data_dir;
|
||||
mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
|
||||
mSkinBaseDir = add(mAppRODataDir, "skins");
|
||||
}
|
||||
mAppName = app_name;
|
||||
|
||||
std::string upper_app_name(app_name);
|
||||
LLStringUtil::toUpper(upper_app_name);
|
||||
|
||||
char* app_home_env = getenv((upper_app_name + "_USER_DIR").c_str()); /* Flawfinder: ignore */
|
||||
auto app_home_env(LLStringUtil::getoptenv(upper_app_name + "_USER_DIR"));
|
||||
if (app_home_env)
|
||||
{
|
||||
// user has specified own userappdir i.e. $SECONDLIFE_USER_DIR
|
||||
mOSUserAppDir = app_home_env;
|
||||
mOSUserAppDir = *app_home_env;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "lldir_solaris.h"
|
||||
#include "llerror.h"
|
||||
#include "llrand.h"
|
||||
#include "llstring.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -41,30 +42,28 @@
|
|||
|
||||
static std::string getCurrentUserHome(char* fallback)
|
||||
{
|
||||
// fwiw this exactly duplicates getCurrentUserHome() in lldir_linux.cpp...
|
||||
// we should either derive both from LLDir_Posix or just axe Solaris.
|
||||
const uid_t uid = getuid();
|
||||
struct passwd *pw;
|
||||
char *result_cstr = fallback;
|
||||
|
||||
|
||||
pw = getpwuid(uid);
|
||||
if ((pw != NULL) && (pw->pw_dir != NULL))
|
||||
{
|
||||
result_cstr = (char*) pw->pw_dir;
|
||||
return pw->pw_dir;
|
||||
}
|
||||
|
||||
LL_INFOS() << "Couldn't detect home directory from passwd - trying $HOME" << LL_ENDL;
|
||||
auto home_env = LLStringUtil::getoptenv("HOME");
|
||||
if (home_env)
|
||||
{
|
||||
return *home_env;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "Couldn't detect home directory from passwd - trying $HOME" << LL_ENDL;
|
||||
const char *const home_env = getenv("HOME"); /* Flawfinder: ignore */
|
||||
if (home_env)
|
||||
{
|
||||
result_cstr = (char*) home_env;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "Couldn't detect home directory! Falling back to " << fallback << LL_ENDL;
|
||||
}
|
||||
LL_WARNS() << "Couldn't detect home directory! Falling back to " << fallback << LL_ENDL;
|
||||
return fallback;
|
||||
}
|
||||
|
||||
return std::string(result_cstr);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -135,27 +134,15 @@ LLDir_Solaris::LLDir_Solaris()
|
|||
//NOTE: Why force people to cd into the package directory?
|
||||
// Look for SECONDLIFE env variable and use it, if set.
|
||||
|
||||
char *dcf = getenv("SECONDLIFE");
|
||||
if(dcf != NULL){
|
||||
(void)strcpy(path, dcf);
|
||||
(void)strcat(path, "/bin"); //NOTE: make sure we point at the bin
|
||||
mExecutableDir = strdup(path);
|
||||
auto SECONDLIFE(LLDirUtil::getoptenv("SECONDLIFE"));
|
||||
if(SECONDLIFE){
|
||||
mExecutableDir = add(*SECONDLIFE, "bin"); //NOTE: make sure we point at the bin
|
||||
}else{
|
||||
// plunk a null at last '/' to get exec dir
|
||||
char *s = execpath + strlen(execpath) -1;
|
||||
while(*s != '/' && s != execpath){
|
||||
--s;
|
||||
}
|
||||
|
||||
if(s != execpath){
|
||||
*s = (char)NULL;
|
||||
|
||||
mExecutableDir = strdup(execpath);
|
||||
LL_INFOS() << "mExecutableDir = [" << mExecutableDir << "]" << LL_ENDL;
|
||||
}
|
||||
mExecutableDir = getDirName(execpath);
|
||||
LL_INFOS() << "mExecutableDir = [" << mExecutableDir << "]" << LL_ENDL;
|
||||
}
|
||||
|
||||
mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin";
|
||||
|
||||
mLLPluginDir = add(mExecutableDir, "llplugin");
|
||||
|
||||
// *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something.
|
||||
mTempDir = "/tmp";
|
||||
|
|
@ -175,17 +162,18 @@ void LLDir_Solaris::initAppDirs(const std::string &app_name,
|
|||
if (!app_read_only_data_dir.empty())
|
||||
{
|
||||
mAppRODataDir = app_read_only_data_dir;
|
||||
mSkinBaseDir = add(mAppRODataDir, "skins");
|
||||
}
|
||||
mAppName = app_name;
|
||||
|
||||
std::string upper_app_name(app_name);
|
||||
LLStringUtil::toUpper(upper_app_name);
|
||||
|
||||
char* app_home_env = getenv((upper_app_name + "_USER_DIR").c_str()); /* Flawfinder: ignore */
|
||||
auto app_home_env(LLStringUtil::getoptenv(upper_app_name + "_USER_DIR"));
|
||||
if (app_home_env)
|
||||
{
|
||||
// user has specified own userappdir i.e. $SECONDLIFE_USER_DIR
|
||||
mOSUserAppDir = app_home_env;
|
||||
mOSUserAppDir = *app_home_env;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -30,7 +30,9 @@
|
|||
|
||||
#include "lldir_win32.h"
|
||||
#include "llerror.h"
|
||||
#include "llrand.h" // for gLindenLabRandomNumber
|
||||
#include "llstring.h"
|
||||
#include "stringize.h"
|
||||
#include "llfile.h"
|
||||
#include <shlobj.h>
|
||||
#include <fstream>
|
||||
|
||||
|
|
@ -43,15 +45,87 @@
|
|||
#define PACKVERSION(major,minor) MAKELONG(minor,major)
|
||||
DWORD GetDllVersion(LPCTSTR lpszDllName);
|
||||
|
||||
namespace
|
||||
{ // anonymous
|
||||
enum class prst { INIT, OPEN, SKIP } state = prst::INIT;
|
||||
// This is called so early that we can't count on static objects being
|
||||
// properly constructed yet, so declare a pointer instead of an instance.
|
||||
std::ofstream* prelogf = nullptr;
|
||||
|
||||
void prelog(const std::string& message)
|
||||
{
|
||||
boost::optional<std::string> prelog_name;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case prst::INIT:
|
||||
// assume we failed, until we succeed
|
||||
state = prst::SKIP;
|
||||
|
||||
prelog_name = LLStringUtil::getoptenv("PRELOG");
|
||||
if (! prelog_name)
|
||||
// no PRELOG variable set, carry on
|
||||
return;
|
||||
prelogf = new llofstream(*prelog_name, std::ios_base::app);
|
||||
if (! (prelogf && prelogf->is_open()))
|
||||
// can't complain to anybody; how?
|
||||
return;
|
||||
// got the log file open, cool!
|
||||
state = prst::OPEN;
|
||||
(*prelogf) << "========================================================================"
|
||||
<< std::endl;
|
||||
// fall through, don't break
|
||||
|
||||
case prst::OPEN:
|
||||
(*prelogf) << message << std::endl;
|
||||
break;
|
||||
|
||||
case prst::SKIP:
|
||||
// either PRELOG isn't set, or we failed to open that pathname
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
#define PRELOG(expression) prelog(STRINGIZE(expression))
|
||||
|
||||
LLDir_Win32::LLDir_Win32()
|
||||
{
|
||||
// set this first: used by append() and add() methods
|
||||
mDirDelimiter = "\\";
|
||||
|
||||
WCHAR w_str[MAX_PATH];
|
||||
// Application Data is where user settings go. We rely on $APPDATA being
|
||||
// correct; in fact the VMP makes a point of setting it properly, since
|
||||
// Windows itself botches the job for non-ASCII usernames (MAINT-8087).
|
||||
mOSUserDir = ll_safe_string(getenv("APPDATA"));
|
||||
// correct.
|
||||
auto APPDATA = LLStringUtil::getoptenv("APPDATA");
|
||||
if (APPDATA)
|
||||
{
|
||||
mOSUserDir = *APPDATA;
|
||||
}
|
||||
PRELOG("APPDATA='" << mOSUserDir << "'");
|
||||
// On Windows, we could have received a plain-ASCII pathname in which
|
||||
// non-ASCII characters have been munged to '?', or the pathname could
|
||||
// have been badly encoded and decoded such that we now have garbage
|
||||
// instead of a valid path. Check that mOSUserDir actually exists.
|
||||
if (mOSUserDir.empty() || ! fileExists(mOSUserDir))
|
||||
{
|
||||
PRELOG("APPDATA does not exist");
|
||||
//HRESULT okay = SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, w_str);
|
||||
wchar_t *pwstr = NULL;
|
||||
HRESULT okay = SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &pwstr);
|
||||
PRELOG("SHGetKnownFolderPath(FOLDERID_RoamingAppData) returned " << okay);
|
||||
if (SUCCEEDED(okay) && pwstr)
|
||||
{
|
||||
// But of course, only update mOSUserDir if SHGetKnownFolderPath() works.
|
||||
mOSUserDir = ll_convert_wide_to_string(pwstr);
|
||||
// Not only that: update our environment so that child processes
|
||||
// will see a reasonable value as well.
|
||||
_wputenv_s(L"APPDATA", pwstr);
|
||||
// SHGetKnownFolderPath() contract requires us to free pwstr
|
||||
CoTaskMemFree(pwstr);
|
||||
PRELOG("mOSUserDir='" << mOSUserDir << "'");
|
||||
}
|
||||
}
|
||||
|
||||
// We want cache files to go on the local disk, even if the
|
||||
// user is on a network with a "roaming profile".
|
||||
|
|
@ -61,9 +135,34 @@ LLDir_Win32::LLDir_Win32()
|
|||
//
|
||||
// We used to store the cache in AppData\Roaming, and the installer
|
||||
// cleans up that version on upgrade. JC
|
||||
mOSCacheDir = ll_safe_string(getenv("LOCALAPPDATA"));
|
||||
auto LOCALAPPDATA = LLStringUtil::getoptenv("LOCALAPPDATA");
|
||||
if (LOCALAPPDATA)
|
||||
{
|
||||
mOSCacheDir = *LOCALAPPDATA;
|
||||
}
|
||||
PRELOG("LOCALAPPDATA='" << mOSCacheDir << "'");
|
||||
// Windows really does not deal well with pathnames containing non-ASCII
|
||||
// characters. See above remarks about APPDATA.
|
||||
if (mOSCacheDir.empty() || ! fileExists(mOSCacheDir))
|
||||
{
|
||||
PRELOG("LOCALAPPDATA does not exist");
|
||||
//HRESULT okay = SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, w_str);
|
||||
wchar_t *pwstr = NULL;
|
||||
HRESULT okay = SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &pwstr);
|
||||
PRELOG("SHGetKnownFolderPath(FOLDERID_LocalAppData) returned " << okay);
|
||||
if (SUCCEEDED(okay) && pwstr)
|
||||
{
|
||||
// But of course, only update mOSCacheDir if SHGetKnownFolderPath() works.
|
||||
mOSCacheDir = ll_convert_wide_to_string(pwstr);
|
||||
// Update our environment so that child processes will see a
|
||||
// reasonable value as well.
|
||||
_wputenv_s(L"LOCALAPPDATA", pwstr);
|
||||
// SHGetKnownFolderPath() contract requires us to free pwstr
|
||||
CoTaskMemFree(pwstr);
|
||||
PRELOG("mOSCacheDir='" << mOSCacheDir << "'");
|
||||
}
|
||||
}
|
||||
|
||||
WCHAR w_str[MAX_PATH];
|
||||
if (GetTempPath(MAX_PATH, w_str))
|
||||
{
|
||||
if (wcslen(w_str)) /* Flawfinder: ignore */
|
||||
|
|
|
|||
|
|
@ -3343,17 +3343,10 @@ S32 OSMessageBoxWin32(const std::string& text, const std::string& caption, U32 t
|
|||
break;
|
||||
}
|
||||
|
||||
// HACK! Doesn't properly handle wide strings!
|
||||
|
||||
// <FS:ND> Convert to wchar_t, then use MessageBoxW
|
||||
|
||||
// int retval_win = MessageBoxA(NULL, text.c_str(), caption.c_str(), uType);
|
||||
llutf16string textW = utf8str_to_utf16str( text );
|
||||
llutf16string captionW = utf8str_to_utf16str( caption );
|
||||
int retval_win = MessageBoxW(NULL, textW.c_str(), captionW.c_str(), uType);
|
||||
|
||||
// </FS:ND>
|
||||
|
||||
int retval_win = MessageBoxW(NULL, // HWND
|
||||
ll_convert_string_to_wide(text).c_str(),
|
||||
ll_convert_string_to_wide(caption).c_str(),
|
||||
uType);
|
||||
S32 retval;
|
||||
|
||||
switch(retval_win)
|
||||
|
|
|
|||
|
|
@ -27,43 +27,31 @@
|
|||
|
||||
#include "linden_common.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "llfile.h"
|
||||
#include "stringize.h"
|
||||
|
||||
#include "../llcontrol.h"
|
||||
|
||||
#include "../test/lltut.h"
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace tut
|
||||
{
|
||||
|
||||
struct control_group
|
||||
{
|
||||
LLControlGroup* mCG;
|
||||
std::unique_ptr<LLControlGroup> mCG;
|
||||
std::string mTestConfigDir;
|
||||
std::string mTestConfigFile;
|
||||
std::vector<std::string> mCleanups;
|
||||
static bool mListenerFired;
|
||||
control_group()
|
||||
{
|
||||
mCG = new LLControlGroup("foo");
|
||||
mCG.reset(new LLControlGroup("foo"));
|
||||
LLUUID random;
|
||||
random.generate();
|
||||
// generate temp dir
|
||||
std::ostringstream oStr;
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
char* tmp_dir = getenv("TMP");
|
||||
if(tmp_dir)
|
||||
{
|
||||
oStr << tmp_dir << "/llcontrol-test-" << random << "/";
|
||||
}
|
||||
else
|
||||
{
|
||||
oStr << "c:/tmp/llcontrol-test-" << random << "/";
|
||||
}
|
||||
#else
|
||||
oStr << "/tmp/llcontrol-test-" << random << "/";
|
||||
#endif
|
||||
|
||||
mTestConfigDir = oStr.str();
|
||||
mTestConfigDir = STRINGIZE(LLFile::tmpdir() << "llcontrol-test-" << random << "/");
|
||||
mTestConfigFile = mTestConfigDir + "settings.xml";
|
||||
LLFile::mkdir(mTestConfigDir);
|
||||
LLSD config;
|
||||
|
|
@ -76,7 +64,12 @@ namespace tut
|
|||
~control_group()
|
||||
{
|
||||
//Remove test files
|
||||
delete mCG;
|
||||
for (auto filename : mCleanups)
|
||||
{
|
||||
LLFile::remove(filename);
|
||||
}
|
||||
LLFile::remove(mTestConfigFile);
|
||||
LLFile::rmdir(mTestConfigDir);
|
||||
}
|
||||
void writeSettingsFile(const LLSD& config)
|
||||
{
|
||||
|
|
@ -118,6 +111,7 @@ namespace tut
|
|||
ensure_equals("value of changed setting", mCG->getU32("TestSetting"), 13);
|
||||
LLControlGroup test_cg("foo2");
|
||||
std::string temp_test_file = (mTestConfigDir + "setting_llsd_temp.xml");
|
||||
mCleanups.push_back(temp_test_file);
|
||||
mCG->saveToFile(temp_test_file.c_str(), TRUE);
|
||||
results = test_cg.loadFromFile(temp_test_file.c_str());
|
||||
ensure("number of changed settings loaded", (results == 1));
|
||||
|
|
@ -139,6 +133,7 @@ namespace tut
|
|||
ensure_equals("value of changed setting", mCG->getU32("TestSetting"), 13);
|
||||
LLControlGroup test_cg("foo3");
|
||||
std::string temp_test_file = (mTestConfigDir + "setting_llsd_persist_temp.xml");
|
||||
mCleanups.push_back(temp_test_file);
|
||||
mCG->saveToFile(temp_test_file.c_str(), TRUE);
|
||||
results = test_cg.loadFromFile(temp_test_file.c_str());
|
||||
//If we haven't changed any settings, then we shouldn't have any settings to load
|
||||
|
|
@ -153,7 +148,7 @@ namespace tut
|
|||
ensure("number of settings", (results == 1));
|
||||
mCG->getControl("TestSetting")->getSignal()->connect(boost::bind(&this->handleListenerTest));
|
||||
mCG->setU32("TestSetting", 13);
|
||||
ensure("listener fired on changed setting", mListenerFired);
|
||||
ensure("listener fired on changed setting", mListenerFired);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1918,7 +1918,6 @@ if (WINDOWS)
|
|||
kernel32
|
||||
odbc32
|
||||
odbccp32
|
||||
ole32
|
||||
oleaut32
|
||||
shell32
|
||||
Vfw32
|
||||
|
|
|
|||
|
|
@ -18,8 +18,7 @@
|
|||
;;
|
||||
;; Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
;;
|
||||
;; NSIS Unicode 2.46.5 or higher required
|
||||
;; http://www.scratchpaper.com/
|
||||
;; NSIS 3 or higher required for Unicode support
|
||||
;;
|
||||
;; Author: James Cook, TankMaster Finesmith, Don Kjer, Callum Prentice
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
|
@ -27,6 +26,7 @@
|
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Compiler flags
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
Unicode true
|
||||
SetOverwrite on # Overwrite files
|
||||
SetCompress auto # Compress if saves space
|
||||
SetCompressor /solid lzma # Compress whole installer as one block
|
||||
|
|
@ -46,28 +46,33 @@ RequestExecutionLevel highest # match MULTIUSER_EXECUTIONLEVEL
|
|||
;; (these files are in the same place as the nsi template but the python script generates a new nsi file in the
|
||||
;; application directory so we have to add a path to these include files)
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
!include "%%SOURCE%%\installers\windows\lang_en-us.nsi" # <FS:Ansariel> Make sure EN comes first as it will be default!
|
||||
!include "%%SOURCE%%\installers\windows\lang_da.nsi"
|
||||
;; Ansariel notes: "Under certain circumstances the installer will fall back
|
||||
;; to the first defined (aka default) language version. So you want to include
|
||||
;; en-us as first language file."
|
||||
!include "%%SOURCE%%\installers\windows\lang_en-us.nsi"
|
||||
|
||||
# Danish and Polish no longer supported by the viewer itself
|
||||
##!include "%%SOURCE%%\installers\windows\lang_da.nsi"
|
||||
!include "%%SOURCE%%\installers\windows\lang_de.nsi"
|
||||
!include "%%SOURCE%%\installers\windows\lang_es.nsi"
|
||||
!include "%%SOURCE%%\installers\windows\lang_fr.nsi"
|
||||
!include "%%SOURCE%%\installers\windows\lang_ja.nsi"
|
||||
!include "%%SOURCE%%\installers\windows\lang_it.nsi"
|
||||
!include "%%SOURCE%%\installers\windows\lang_pl.nsi"
|
||||
##!include "%%SOURCE%%\installers\windows\lang_pl.nsi"
|
||||
!include "%%SOURCE%%\installers\windows\lang_pt-br.nsi"
|
||||
!include "%%SOURCE%%\installers\windows\lang_ru.nsi"
|
||||
!include "%%SOURCE%%\installers\windows\lang_tr.nsi"
|
||||
!include "%%SOURCE%%\installers\windows\lang_zh.nsi"
|
||||
|
||||
# *TODO: Move these into the language files themselves
|
||||
LangString LanguageCode ${LANG_DANISH} "da"
|
||||
##LangString LanguageCode ${LANG_DANISH} "da"
|
||||
LangString LanguageCode ${LANG_GERMAN} "de"
|
||||
LangString LanguageCode ${LANG_ENGLISH} "en"
|
||||
LangString LanguageCode ${LANG_SPANISH} "es"
|
||||
LangString LanguageCode ${LANG_FRENCH} "fr"
|
||||
LangString LanguageCode ${LANG_JAPANESE} "ja"
|
||||
LangString LanguageCode ${LANG_ITALIAN} "it"
|
||||
LangString LanguageCode ${LANG_POLISH} "pl"
|
||||
##LangString LanguageCode ${LANG_POLISH} "pl"
|
||||
LangString LanguageCode ${LANG_PORTUGUESEBR} "pt"
|
||||
LangString LanguageCode ${LANG_RUSSIAN} "ru"
|
||||
LangString LanguageCode ${LANG_TURKISH} "tr"
|
||||
|
|
@ -114,12 +119,14 @@ SetOverwrite on # Overwrite files by default
|
|||
# should make MultiUser.nsh initialization read existing INSTDIR from registry
|
||||
!define MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY "${INSTNAME_KEY}"
|
||||
!define MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME ""
|
||||
# should make MultiUser.nsh initialization write $MultiUser.InstallMode to registry
|
||||
!define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY "${INSTNAME_KEY}"
|
||||
!define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME "InstallMode"
|
||||
# Don't set MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY and
|
||||
# MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME to cause the installer to
|
||||
# write $MultiUser.InstallMode to the registry, because when the user installs
|
||||
# multiple viewers with the same channel (same ${INSTNAME}, hence same
|
||||
# ${INSTNAME_KEY}), the registry entry is overwritten. Instead we'll write a
|
||||
# little file into the install directory -- see .onInstSuccess and un.onInit.
|
||||
!include MultiUser.nsh
|
||||
!include MUI2.nsh
|
||||
|
||||
!define MUI_BGCOLOR FFFFFF
|
||||
!insertmacro MUI_FUNCTION_GUIINIT
|
||||
|
||||
|
|
@ -242,8 +249,6 @@ lbl_configure_default_lang:
|
|||
# </FS:Ansariel>
|
||||
StrCmp $SKIP_DIALOGS "true" lbl_return
|
||||
|
||||
# <FS:Ansariel> Commented out; Warning in build log about not being used
|
||||
;lbl_build_menu:
|
||||
Push ""
|
||||
# Use separate file so labels can be UTF-16 but we can still merge changes into this ASCII file. JC
|
||||
!include "%%SOURCE%%\installers\windows\language_menu.nsi"
|
||||
|
|
@ -267,7 +272,21 @@ FunctionEnd
|
|||
;; Prep Uninstaller Section
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
Function un.onInit
|
||||
!insertmacro MULTIUSER_UNINIT
|
||||
# Save $INSTDIR -- it appears to have the correct value before
|
||||
# MULTIUSER_UNINIT, but then gets munged by MULTIUSER_UNINIT?!
|
||||
Push $INSTDIR
|
||||
!insertmacro MULTIUSER_UNINIT
|
||||
Pop $INSTDIR
|
||||
|
||||
# Now read InstallMode.txt from $INSTDIR
|
||||
Push $0
|
||||
ClearErrors
|
||||
FileOpen $0 "$INSTDIR\InstallMode.txt" r
|
||||
IfErrors skipread
|
||||
FileRead $0 $MultiUser.InstallMode
|
||||
FileClose $0
|
||||
skipread:
|
||||
Pop $0
|
||||
|
||||
%%ENGAGEREGISTRY%%
|
||||
|
||||
|
|
@ -276,10 +295,10 @@ Function un.onInit
|
|||
IfErrors lbl_end
|
||||
StrCpy $LANGUAGE $0
|
||||
lbl_end:
|
||||
Return
|
||||
|
||||
# Does MultiUser.nsh init read back
|
||||
# MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY into $MultiUser.InstallMode?
|
||||
## MessageBox MB_OK "After restoring:$\n$$INSTDIR = '$INSTDIR'$\n$$MultiUser.InstallMode = '$MultiUser.InstallMode'$\n$$LANGUAGE = '$LANGUAGE'"
|
||||
|
||||
Return
|
||||
|
||||
FunctionEnd
|
||||
|
||||
|
|
@ -474,8 +493,10 @@ StrCpy $INSTSHORTCUT "${SHORTCUT}"
|
|||
# MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME
|
||||
# Couln't get NSIS to expand $MultiUser.InstallMode into the function name at Call time
|
||||
${If} $MultiUser.InstallMode == 'AllUsers'
|
||||
##MessageBox MB_OK "Uninstalling for all users"
|
||||
Call un.MultiUser.InstallMode.AllUsers
|
||||
${Else}
|
||||
##MessageBox MB_OK "Uninstalling for current user"
|
||||
Call un.MultiUser.InstallMode.CurrentUser
|
||||
${EndIf}
|
||||
|
||||
|
|
@ -688,6 +709,9 @@ Function un.ProgramFiles
|
|||
# This placeholder is replaced by the complete list of files to uninstall by viewer_manifest.py
|
||||
%%DELETE_FILES%%
|
||||
|
||||
# our InstallMode.txt
|
||||
Delete "$INSTDIR\InstallMode.txt"
|
||||
|
||||
# Optional/obsolete files. Delete won't fail if they don't exist.
|
||||
Delete "$INSTDIR\autorun.bat"
|
||||
Delete "$INSTDIR\dronesettings.ini"
|
||||
|
|
@ -737,7 +761,12 @@ FunctionEnd
|
|||
;; After install completes, launch app
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
Function .onInstSuccess
|
||||
Call CheckWindowsServPack # Warn if not on the latest SP before asking to launch.
|
||||
Push $0
|
||||
FileOpen $0 "$INSTDIR\InstallMode.txt" w
|
||||
# No newline -- this is for our use, not for users to read.
|
||||
FileWrite $0 "$MultiUser.InstallMode"
|
||||
FileClose $0
|
||||
Pop $0
|
||||
# <FS:Ansariel> Disable VMP
|
||||
#Push $R0
|
||||
#Push $0
|
||||
|
|
@ -760,24 +789,21 @@ Function .onInstSuccess
|
|||
#Pop $0
|
||||
#Pop $R0
|
||||
# </FS:Ansariel>
|
||||
Push $R0 # Option value, unused#
|
||||
# <FS:PP> Disable autorun
|
||||
# StrCmp $SKIP_AUTORUN "true" +2;
|
||||
# Assumes SetOutPath $INSTDIR
|
||||
# Exec '"$WINDIR\explorer.exe" "$INSTDIR\$INSTEXE"'
|
||||
# Pop $R0
|
||||
StrCmp $SKIP_DIALOGS "true" label_launch
|
||||
|
||||
${GetOptions} $COMMANDLINE "/AUTOSTART" $R0
|
||||
# If parameter was there (no error) just launch
|
||||
# Otherwise ask
|
||||
IfErrors label_ask_launch label_launch
|
||||
Call CheckWindowsServPack # Warn if not on the latest SP before asking to launch.
|
||||
# <FS:PP> Disable autorun
|
||||
#StrCmp $SKIP_AUTORUN "true" +2;
|
||||
StrCmp $SKIP_DIALOGS "true" label_launch
|
||||
|
||||
${GetOptions} $COMMANDLINE "/AUTOSTART" $R0
|
||||
# If parameter was there (no error) just launch
|
||||
# Otherwise ask
|
||||
IfErrors label_ask_launch label_launch
|
||||
|
||||
label_ask_launch:
|
||||
# Don't launch by default when silent
|
||||
IfSilent label_no_launch
|
||||
MessageBox MB_YESNO $(InstSuccesssQuestion) \
|
||||
IDYES label_launch IDNO label_no_launch
|
||||
# Don't launch by default when silent
|
||||
IfSilent label_no_launch
|
||||
MessageBox MB_YESNO $(InstSuccesssQuestion) IDYES label_launch IDNO label_no_launch
|
||||
|
||||
label_launch:
|
||||
# Assumes SetOutPath $INSTDIR
|
||||
|
|
@ -796,10 +822,9 @@ label_launch:
|
|||
# string because it must decompose into separate command-line tokens.
|
||||
# <FS:Ansariel> No updater, thanks!
|
||||
# Exec '"$INSTDIR\$INSTEXE" precheck "$INSTDIR\$VIEWER_EXE" $SHORTCUT_LANG_PARAM'
|
||||
Exec '"$WINDIR\explorer.exe" "$INSTDIR\$INSTSHORTCUT.lnk"'
|
||||
Exec '"$WINDIR\explorer.exe" "$INSTDIR\$INSTSHORTCUT.lnk"'
|
||||
label_no_launch:
|
||||
Pop $R0
|
||||
# </FS:PP>
|
||||
# </FS:PP>
|
||||
FunctionEnd
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -674,7 +674,9 @@ bool LLAppViewerWin32::init()
|
|||
|
||||
std::string build_data_fname(
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "build_data.json"));
|
||||
std::ifstream inf(build_data_fname.c_str());
|
||||
// Use llifstream instead of std::ifstream because LL_PATH_EXECUTABLE
|
||||
// could contain non-ASCII characters, which std::ifstream doesn't handle.
|
||||
llifstream inf(build_data_fname.c_str());
|
||||
if (! inf.is_open())
|
||||
{
|
||||
LL_WARNS() << "Can't initialize BugSplat, can't read '" << build_data_fname
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "llui.h"
|
||||
#include "llprocess.h"
|
||||
#include "llsdutil.h"
|
||||
#include "llstring.h"
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
// static
|
||||
|
|
@ -206,12 +207,12 @@ std::string LLExternalEditor::findCommand(
|
|||
cmd = LLUI::sSettingGroups["config"]->getString(sSetting);
|
||||
LL_INFOS() << "Using setting" << LL_ENDL;
|
||||
}
|
||||
else // otherwise use the path specified by the environment variable
|
||||
else // otherwise use the path specified by the environment variable
|
||||
{
|
||||
char* env_var_val = getenv(env_var.c_str());
|
||||
auto env_var_val(LLStringUtil::getoptenv(env_var));
|
||||
if (env_var_val)
|
||||
{
|
||||
cmd = env_var_val;
|
||||
cmd = *env_var_val;
|
||||
LL_INFOS() << "Using env var " << env_var << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "llimagepng.h"
|
||||
|
||||
#include "llsdserialize.h"
|
||||
#include "llstring.h"
|
||||
|
||||
// newview
|
||||
#include "llpanelprofile.h" // for getProfileURL(). FIXME: move the method to LLAvatarActions
|
||||
|
|
@ -264,6 +265,5 @@ void LLWebProfile::reportImageUploadStatus(bool ok)
|
|||
std::string LLWebProfile::getAuthCookie()
|
||||
{
|
||||
// This is needed to test image uploads on Linux viewer built with OpenSSL 1.0.0 (0.9.8 works fine).
|
||||
const char* debug_cookie = getenv("LL_SNAPSHOT_COOKIE");
|
||||
return debug_cookie ? debug_cookie : sAuthCookie;
|
||||
return LLStringUtil::getenv("LL_SNAPSHOT_COOKIE", sAuthCookie);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -561,6 +561,7 @@ class WindowsManifest(ViewerManifest):
|
|||
#with self.prefix(src=os.path.join(pkgdir, "VMP")):
|
||||
# include the compiled launcher scripts so that it gets included in the file_list
|
||||
# self.path('SLVersionChecker.exe')
|
||||
# self.path('nextviewer.bat')
|
||||
|
||||
#with self.prefix(dst="vmp_icons"):
|
||||
# with self.prefix(src=self.icon_path()):
|
||||
|
|
@ -956,12 +957,10 @@ class WindowsManifest(ViewerManifest):
|
|||
# ):
|
||||
# self.sign(exe)
|
||||
|
||||
# We use the Unicode version of NSIS, available from
|
||||
# http://www.scratchpaper.com/
|
||||
# Check two paths, one for Program Files, and one for Program Files (x86).
|
||||
# Yay 64bit windows.
|
||||
for ProgramFiles in 'ProgramFiles', 'ProgramFiles(x86)':
|
||||
NSIS_path = os.path.expandvars(r'${%s}\NSIS\Unicode\makensis.exe' % ProgramFiles)
|
||||
NSIS_path = os.path.expandvars(r'${%s}\NSIS\makensis.exe' % ProgramFiles)
|
||||
if os.path.exists(NSIS_path):
|
||||
break
|
||||
installer_created=False
|
||||
|
|
|
|||
|
|
@ -95,7 +95,6 @@ target_link_libraries(windows-crash-logger
|
|||
${GOOGLE_PERFTOOLS_LIBRARIES}
|
||||
user32
|
||||
gdi32
|
||||
ole32
|
||||
oleaut32
|
||||
wininet
|
||||
Wldap32
|
||||
|
|
|
|||
Loading…
Reference in New Issue