From dd9f6784ccc5d285ef50f0b8693ee92bb872d992 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 15 Nov 2018 12:06:30 -0500 Subject: [PATCH 01/38] SL-10010: Use c:\Program Files rather than c:\Program Files (x86) for 64-bit viewers. It seems there's a longstanding bug in NSIS: it fails to use $PROGRAMFILES64 rather than $PROGRAMFILES when performing an all-users install of a 64-bit program. Try to remedy that. Also pick up a few NSIS suggestions from Ansariel Hiller. --- .../installers/windows/installer_template.nsi | 22 +++++++++++++++++- .../newview/installers/windows/lang_en-us.nsi | Bin 11342 -> 11488 bytes 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi index bd290b710b..840203c178 100644 --- a/indra/newview/installers/windows/installer_template.nsi +++ b/indra/newview/installers/windows/installer_template.nsi @@ -46,9 +46,13 @@ 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) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 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" + !include "%%SOURCE%%\installers\windows\lang_da.nsi" !include "%%SOURCE%%\installers\windows\lang_de.nsi" -!include "%%SOURCE%%\installers\windows\lang_en-us.nsi" !include "%%SOURCE%%\installers\windows\lang_es.nsi" !include "%%SOURCE%%\installers\windows\lang_fr.nsi" !include "%%SOURCE%%\installers\windows\lang_ja.nsi" @@ -108,8 +112,22 @@ AutoCloseWindow true # After all files install, close window !define MULTIUSER_INSTALLMODE_COMMANDLINE # appended to $PROGRAMFILES, as affected by MULTIUSER_USE_PROGRAMFILES64 !define MULTIUSER_INSTALLMODE_INSTDIR "${INSTNAME}" + # expands to !define MULTIUSER_USE_PROGRAMFILES64 or nothing %%PROGRAMFILES%% +# Bug in MultiUser.nsh?! This reference: +# http://nsis.sourceforge.net/Docs/MultiUser/Readme.html +# says: +# MULTIUSER_USE_PROGRAMFILES64 Use $PROGRAMFILES64 instead of $PROGRAMFILES as the default all users directory. +# Yet as far as I can tell from: +# https://sourceforge.net/p/nsis/mailman/message/22246769/ +# (which contains a patch), that functionality has never been released with +# NSIS. Instead of applying a patch to each developer machine and each +# TeamCity build host, try overwriting $PROGRAMFILES with $PROGRAMFILES64?! +!ifdef MULTIUSER_USE_PROGRAMFILES64 + StrCpy $PROGRAMFILES $PROGRAMFILES64 +!endif + # should make MultiUser.nsh initialization read existing INSTDIR from registry !define MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY "${INSTNAME_KEY}" !define MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME "" @@ -118,6 +136,8 @@ AutoCloseWindow true # After all files install, close window !define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME "InstallMode" !include MultiUser.nsh !include MUI2.nsh +!define MUI_BGCOLOR FFFFFF +!insertmacro MUI_FUNCTION_GUIINIT UninstallText $(UninstallTextMsg) DirText $(DirectoryChooseTitle) $(DirectoryChooseSetup) diff --git a/indra/newview/installers/windows/lang_en-us.nsi b/indra/newview/installers/windows/lang_en-us.nsi index 1e81c5294ac8b1ce576bd47c2fed0e61d76993bc..fd4d340816abc487166547c2ec01d4a9ac58cf88 100644 GIT binary patch delta 264 zcmXv|I}UP{Scmeeac9zcb zlg-=RnKy6d6_dyGSZL~{UzD#mt7ELOzy=l$h_U6H@)n%46ChJ3)0m~idm`a1^xz{R z5>-NdfE_EO&x)0yMgH&RVgAv1oQ!!gD#S}t#chF9UCWiu*R4+M(8WQ6Di2+_7%?Fx um(nRBJNRW~u+&|%+crIAr-Y|ZP0n&L@E2ZxwB+F4fC9oZnZb}{5d%Q delta 46 zcmV+}0MY;8S Date: Thu, 15 Nov 2018 16:02:47 -0500 Subject: [PATCH 02/38] SL-10010: Use trunk NSIS + Unicode attrib, instead of Unicode fork. Back out misguided attempt to overwrite $PROGRAMFILES with $PROGRAMFILES64. --- .../installers/windows/installer_template.nsi | 18 ++---------------- indra/newview/viewer_manifest.py | 4 +--- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi index 840203c178..f62a14d65f 100644 --- a/indra/newview/installers/windows/installer_template.nsi +++ b/indra/newview/installers/windows/installer_template.nsi @@ -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 @@ -112,22 +112,8 @@ AutoCloseWindow true # After all files install, close window !define MULTIUSER_INSTALLMODE_COMMANDLINE # appended to $PROGRAMFILES, as affected by MULTIUSER_USE_PROGRAMFILES64 !define MULTIUSER_INSTALLMODE_INSTDIR "${INSTNAME}" - # expands to !define MULTIUSER_USE_PROGRAMFILES64 or nothing %%PROGRAMFILES%% -# Bug in MultiUser.nsh?! This reference: -# http://nsis.sourceforge.net/Docs/MultiUser/Readme.html -# says: -# MULTIUSER_USE_PROGRAMFILES64 Use $PROGRAMFILES64 instead of $PROGRAMFILES as the default all users directory. -# Yet as far as I can tell from: -# https://sourceforge.net/p/nsis/mailman/message/22246769/ -# (which contains a patch), that functionality has never been released with -# NSIS. Instead of applying a patch to each developer machine and each -# TeamCity build host, try overwriting $PROGRAMFILES with $PROGRAMFILES64?! -!ifdef MULTIUSER_USE_PROGRAMFILES64 - StrCpy $PROGRAMFILES $PROGRAMFILES64 -!endif - # should make MultiUser.nsh initialization read existing INSTDIR from registry !define MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY "${INSTNAME_KEY}" !define MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME "" diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 3e8bb388d2..32773b2c36 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -830,12 +830,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 From 8420e20102006b780d6959ec3d0fa6d905a32f16 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 21 Nov 2018 09:53:45 -0500 Subject: [PATCH 03/38] DRTVWR-447: Fix syntax error in embedded variable reference. --- indra/newview/installers/windows/lang_ru.nsi | Bin 9188 -> 9186 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/indra/newview/installers/windows/lang_ru.nsi b/indra/newview/installers/windows/lang_ru.nsi index a42c7191697bbaaf8089ccfa5ae31a4b6b022cd6..d8990fd9553c0deb9bd020015b3d68ca500e9622 100644 GIT binary patch delta 16 XcmaFj{>XiUfav5nVVTW(qTBcYJ8A|5 delta 14 VcmaFl{=|KQfGDHFW`5Djd;ly@1p@#8 From 24872bea74a9275b388a4306091f940ccbf80270 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 21 Nov 2018 09:55:54 -0500 Subject: [PATCH 04/38] DRTVWR-447: Fix longstanding NSIS warning about unused label. --- indra/newview/installers/windows/installer_template.nsi | 1 - 1 file changed, 1 deletion(-) diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi index f62a14d65f..355272cd08 100644 --- a/indra/newview/installers/windows/installer_template.nsi +++ b/indra/newview/installers/windows/installer_template.nsi @@ -216,7 +216,6 @@ lbl_configure_default_lang: Goto lbl_return StrCmp $SKIP_DIALOGS "true" lbl_return -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" From 7ca89229f86aa8c056b45be1b59d221799e56a84 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 21 Nov 2018 12:07:18 -0500 Subject: [PATCH 05/38] SL-10077: Save correct uninstall directory and (un)install mode. Curiously, the value of $INSTDIR is correct before MULTIUSER_UNINIT, but is made incorrect by MULTIUSER_UNINIT. Save and restore the correct value. Saving $MultiUser.InstallMode in the registry (by setting relevant macros examined by MultiUser.nsh) is susceptible to overwriting if the user installs multiple viewers with the same channel name. Instead, write an InstallMode.txt in the install directory, and read it back on uninstall. Of course, add it to the files to be deleted on uninstall. --- .../installers/windows/installer_template.nsi | 48 +++++++++++++++---- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi index 355272cd08..b2d376d0c0 100644 --- a/indra/newview/installers/windows/installer_template.nsi +++ b/indra/newview/installers/windows/installer_template.nsi @@ -117,9 +117,12 @@ AutoCloseWindow true # After all files install, close window # 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 @@ -239,7 +242,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%% @@ -248,10 +265,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 @@ -417,8 +434,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} @@ -626,6 +645,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" @@ -675,7 +697,13 @@ 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 + Push $R0 Push $0 ;; MAINT-7812: Only write nsis.winstall file with /marker switch @@ -694,7 +722,8 @@ Function .onInstSuccess ClearErrors Pop $0 Pop $R0 - Push $R0 # Option value, unused# + + Call CheckWindowsServPack # Warn if not on the latest SP before asking to launch. StrCmp $SKIP_AUTORUN "true" +2; # Assumes SetOutPath $INSTDIR # Run INSTEXE (our updater), passing VIEWER_EXE plus the command-line @@ -711,7 +740,6 @@ Function .onInstSuccess # must be a distinct command-line token, but DO NOT quote the language # string because it must decompose into separate command-line tokens. Exec '"$INSTDIR\$INSTEXE" precheck "$INSTDIR\$VIEWER_EXE" $SHORTCUT_LANG_PARAM' - Pop $R0 # FunctionEnd From feb886e08a3cc3ce9a64a16e72cb17b3d5910ab3 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 21 Nov 2018 14:40:12 -0500 Subject: [PATCH 06/38] DRTVWR-447: Update to viewer-manager build 521943 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index a51f14b274..5a0194cf86 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3138,9 +3138,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - c543e73c35c605eaf509bc7651c11227 + 15e764eb3a0efefe0eda103c72407ab4 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/27348/219718/viewer_manager-2.0.521526-darwin64-521526.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/27985/227818/viewer_manager-2.0.521943-darwin64-521943.tar.bz2 name darwin64 @@ -3162,9 +3162,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - fec612973e0d70f82da8c8f22a10c6f3 + ea65e1c59d34f19c64fa2a1b32d312ad url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/27349/219725/viewer_manager-2.0.521526-windows-521526.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/27986/227825/viewer_manager-2.0.521943-windows-521943.tar.bz2 name windows @@ -3175,7 +3175,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.521526 + 2.0.521943 vlc-bin From a5b624fe3aac98655a0fec23044e7fbf6326c4db Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 27 Nov 2018 17:28:21 -0500 Subject: [PATCH 07/38] SL-10030: Update to viewer-manager build 522023 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 5a0194cf86..553b8ade24 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3138,9 +3138,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 15e764eb3a0efefe0eda103c72407ab4 + 7f4af59da23c015cd9cfcdd567a5966d url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/27985/227818/viewer_manager-2.0.521943-darwin64-521943.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28113/229287/viewer_manager-2.0.522023-darwin64-522023.tar.bz2 name darwin64 @@ -3162,9 +3162,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - ea65e1c59d34f19c64fa2a1b32d312ad + 105a3eb51d99cbf6fcf4f65a7f1c3f31 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/27986/227825/viewer_manager-2.0.521943-windows-521943.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28114/229293/viewer_manager-2.0.522023-windows-522023.tar.bz2 name windows @@ -3175,7 +3175,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.521943 + 2.0.522023 vlc-bin From c54d3eaa7d63ca7f864886544abe68f9be1441e5 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 28 Nov 2018 07:11:21 -0500 Subject: [PATCH 08/38] SL-10030: Update to viewer-manager build 522036 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 553b8ade24..b474265f40 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3138,9 +3138,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 7f4af59da23c015cd9cfcdd567a5966d + aa6b3ad6366967f546c9144456b8f58a url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28113/229287/viewer_manager-2.0.522023-darwin64-522023.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28129/229691/viewer_manager-2.0.522036-darwin64-522036.tar.bz2 name darwin64 @@ -3162,9 +3162,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 105a3eb51d99cbf6fcf4f65a7f1c3f31 + 958221ef0fd6d542f7c12d18383ec34a url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28114/229293/viewer_manager-2.0.522023-windows-522023.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28130/229697/viewer_manager-2.0.522036-windows-522036.tar.bz2 name windows @@ -3175,7 +3175,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.522023 + 2.0.522036 vlc-bin From 58634033918b2be86534120e08d3b49a4ebcef5a Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 28 Nov 2018 15:59:06 -0500 Subject: [PATCH 09/38] SL-10030: Update to viewer-manager build 522055 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index b474265f40..2d63f2e3ab 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3138,9 +3138,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - aa6b3ad6366967f546c9144456b8f58a + 499b1cfb532786a4dee27d68e84c928b url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28129/229691/viewer_manager-2.0.522036-darwin64-522036.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28164/229888/viewer_manager-2.0.522055-darwin64-522055.tar.bz2 name darwin64 @@ -3162,9 +3162,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 958221ef0fd6d542f7c12d18383ec34a + 220eba0d32d7ad14c783aa1e09e5e7e9 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28130/229697/viewer_manager-2.0.522036-windows-522036.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28165/229894/viewer_manager-2.0.522055-windows-522055.tar.bz2 name windows @@ -3175,7 +3175,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.522036 + 2.0.522055 vlc-bin From 31b6d83606daff4dfcb18ead9db4a0d5a6b82c74 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 28 Nov 2018 16:00:27 -0500 Subject: [PATCH 10/38] SL-10030: Include nextviewer.bat in the Windows install directory. --- indra/newview/viewer_manifest.py | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 32773b2c36..4e8df5ce29 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -498,6 +498,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()): From ed5dfb0b2f8dfc4f5163fed324909c0c012df391 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 28 Nov 2018 18:32:48 -0500 Subject: [PATCH 11/38] SL-10030: Update to viewer-manager build 522068 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 2d63f2e3ab..9e1a54dca3 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3138,9 +3138,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 499b1cfb532786a4dee27d68e84c928b + 3fb7877981cf1ca6a79addf2e279a751 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28164/229888/viewer_manager-2.0.522055-darwin64-522055.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28187/230154/viewer_manager-2.0.522068-darwin64-522068.tar.bz2 name darwin64 @@ -3162,9 +3162,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 220eba0d32d7ad14c783aa1e09e5e7e9 + 59e9894657f0175a5c84b459098584b9 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28165/229894/viewer_manager-2.0.522055-windows-522055.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28188/230160/viewer_manager-2.0.522068-windows-522068.tar.bz2 name windows @@ -3175,7 +3175,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.522055 + 2.0.522068 vlc-bin From ff802c5cd20d299c773cf58cb75ff8d62aec1c11 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 28 Nov 2018 22:02:50 -0500 Subject: [PATCH 12/38] SL-10030: Update to viewer-manager build 522079 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 9e1a54dca3..5dfab783d6 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3138,9 +3138,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 3fb7877981cf1ca6a79addf2e279a751 + 1859ebf1b12485211ef4243b48c19410 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28187/230154/viewer_manager-2.0.522068-darwin64-522068.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28203/230495/viewer_manager-2.0.522079-darwin64-522079.tar.bz2 name darwin64 @@ -3162,9 +3162,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 59e9894657f0175a5c84b459098584b9 + e6251d211ac0b5b4258c3a04fd5f3ffe url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28188/230160/viewer_manager-2.0.522068-windows-522068.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28204/230501/viewer_manager-2.0.522079-windows-522079.tar.bz2 name windows @@ -3175,7 +3175,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.522068 + 2.0.522079 vlc-bin From 4d9ad4612a9db32cda11a4ca62baf9ae90ae26ee Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 29 Nov 2018 14:49:19 -0500 Subject: [PATCH 13/38] SL-10030: Update to viewer-manager build 522096 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 5dfab783d6..a063e4be0e 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3138,9 +3138,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 1859ebf1b12485211ef4243b48c19410 + 2040ddeb5dd2040f9d57bdc1865af520 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28203/230495/viewer_manager-2.0.522079-darwin64-522079.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28232/230664/viewer_manager-2.0.522096-darwin64-522096.tar.bz2 name darwin64 @@ -3162,9 +3162,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - e6251d211ac0b5b4258c3a04fd5f3ffe + a3c4980f31e3437910b72bd45efb0e6d url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28204/230501/viewer_manager-2.0.522079-windows-522079.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28233/230672/viewer_manager-2.0.522096-windows-522096.tar.bz2 name windows @@ -3175,7 +3175,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.522079 + 2.0.522096 vlc-bin From 63117d291936310b2059f07c79c3ccc87baaa064 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 30 Nov 2018 15:06:27 -0500 Subject: [PATCH 14/38] SL-10147: Copy placeholder English text to supported NSIS languages. --- indra/newview/installers/windows/lang_da.nsi | Bin 7816 -> 11760 bytes indra/newview/installers/windows/lang_de.nsi | Bin 9854 -> 12582 bytes indra/newview/installers/windows/lang_es.nsi | Bin 9876 -> 12630 bytes indra/newview/installers/windows/lang_fr.nsi | Bin 10262 -> 12990 bytes indra/newview/installers/windows/lang_it.nsi | Bin 9524 -> 12278 bytes indra/newview/installers/windows/lang_ja.nsi | Bin 7208 -> 9988 bytes indra/newview/installers/windows/lang_pl.nsi | Bin 8136 -> 12080 bytes .../newview/installers/windows/lang_pt-br.nsi | Bin 9864 -> 12748 bytes indra/newview/installers/windows/lang_ru.nsi | Bin 9186 -> 11940 bytes indra/newview/installers/windows/lang_tr.nsi | Bin 9290 -> 12044 bytes indra/newview/installers/windows/lang_zh.nsi | Bin 6850 -> 9708 bytes 11 files changed, 0 insertions(+), 0 deletions(-) diff --git a/indra/newview/installers/windows/lang_da.nsi b/indra/newview/installers/windows/lang_da.nsi index b3b8cf34d5ff4fb43aee48cd89a4cd8669dfe359..f462c82078800e8e47544b724af691e9f5e01701 100644 GIT binary patch delta 2557 zcmbtV+fEZv6x~o7kwOV6Sek|~pok5MX^fg+2&r6@SSWJw5-_BcQW{E&!!11Z)fbKC ze25ZE{0@J>KQPf3AAEAHb2>~*3nFIH&YUx|_g;JLwfA{5{A2Nx?NRsIJBJq}F7q-e z3o<9;GAqkijmr!CFJpHayYmvmH*uMggpA=GznH`?F5@cdxvFOBI(-)27Gzb@(yOBF zU85KAItL67t9<*5maM_IEtVuDhs%;(*+wKA|CZdqJuR=Xm(@?)ivh_d)_I9wWo!#r z<>UZs$J>sq!_txzY;A3ummRDf?<3MHEz+d!wufTX`H-7w&DeSPN~qZ7zMkhgVjeLL zfNB?a8~P}3d>?bAoFXS3=I`W+>Nz&it7P?wCTBLLT7k3o6XK{@~ z2J=q)IMD~(=%>kxlxj&HWjr71*^9Rp&{yUCH-j3Ph+PcLiro|X%=sVpi;efD0tG*s#ibo=d-aVzHrSC48S_j~C- zqYk|x)!Wv4pF*h2zqX%R8O+rATeP=h{D-OR=0TVHzLTh9n4#1P=XcedZsSB*0S`9V zU}UYEfwO$n!0nlqg8JGTsAjzHTuJ~Bg95cs!}LK;#vR>x|WXSeRjMiq0nD@%0RM_ZTUF1P(`vW36n|5lc?Tbc$1e zNW)RXT-IKD@3qhT%6&Qg`fWl@O+MV*!y$4gAbZS z<-?A2EPNog0}Ex;d0DtZ3pPhu{C>f=jZ2Qz^p}jK$mE=M0|{DYZPB4%+2!>8E7rKaN% z)-Bp5R*BNWHRohSe`FReI9J0b-gTm$@or&-Ydq`_UX3CF^BNy+_}>wAc;4r9-Y|NrfzW^X^IhCP*G(a?J@P# zBv*;s)Tl0cf}>WW&kDEAzfrKK@nToEkyuX+K5dDT4{z%?O-�%1|jKug5&^%RTR- zG$<+6x>e=r#LbV1-8<5@t3oR~(5l)TVP5({0+MqU-LUEn&VH4{x|Z zL-X;1NKdeggr%LT!yY&$>M}aJ)bOgjPO^mZYex6Bj3K6=j{zEfG7kB`FdtA?Z^U z>>j@u#0V!?Y)Pd%K#tHkowqtxv5kjx+u@u?_s8;H9qf;D4{N~*qj+6eNL^#(7SI;jP1CUM+7 zDULB24$~)T*3wl!Qs&X83+q~5p6)V{lrJ`sU{lL7Qhw_5g-mJ{iu|k;J9daj}gGHaRCNO1xb-%AU=s{i*qs#n~QO@YMJ8qVsR4HOBBb zj6LeY#{dm-w9MWftqx9T2WSJl z=1vPu?(OTnUHY_W`7;`R{ajL#pt4R|lB88oWx}$fXWC(xE>0NKkncX9VoNA(O-F(r zQx}pJjyWeQCW%=%;#?bVd3PA?0dF7oxhBAFGF^h*mUqw0UvP6BFLm$ zV@qy56bW6_d2C`0FHxo29>@BGKjhA>UjazoO{UMw>q=0zyk=^X!4ZYkUgjWi6@Fs0>w?TIme!Yn6UX{6UP5nsUT1mD)+NarC zjbVxWnk=G`v2;|6nvkxPQPG5SohZy`O%&MHvW!)qdN;Q)yM_#|Agz{DHlZZfgr`#^A&yO3E;iWlXZyAeS(td)Inu^_GJu~|)_4A(nnXQ`>k8LL7xiY>ji z#FO`FLN=^jOzp!sF)Xf6vhY|fT{+=!FA0a@xHkDH3!7)TC{F$(k^jY2Il}g}CI-w? iOPcG!pE08GXP3%E5WR&@EnVd?ms}z)rypk;OFsdaVoqxS delta 25 hcmdm&IxS$s1?J5MI6g2fDL=0S=sqL)Shh*F5emM#|+r_Ia$m*WPQN`~LB-^1H7-^?B*yy%I7g zB8?IXNMRFYS}APtS>|YtqeaBICW9>UNODeAqI6xOQ{Uu{@#8B z*r%{64532c47W?nPPywME4qnE4f3b0fswK!_JRmFGPTGgg3@UtNKodRyi(Ln(P=x0 z5O!9w8YLF?cgMBah0H}JinfKcke=y)syb2Y8|xD6RNj` z>c8>aeH&h|wHO7>h}u?ft>uWQ%jithSJRU8RG#{NA)wy)&kLuu$r#2@C9xh(vRWKZ zrTEt^G0=Z3k5u|4NG-vF?hq$t!T4ZO^FQOYs{lLOHDKD(&CO^W$%D!AI1`(VrmH19qSNt+;V+ZWB$GH#bJ3jqNj&}- z^Krb;Cq;*u+7`V<-5f?SJQ!Tb5kWL26&@a!y52)Bp{cm2AHksd?Z0&N!TYvP2S=ABa5z378yB?zhg-SSLiW3$!<>>QQVku>S zaq#Qf%1nrUW+ZcGsTers`T;)i9CR9gbVVuWU>o~*#fsw82@P(%@1 zTeuW_SvF7K=L;8PKi`uQ?bsf!GnSM!rfl=ytMvW5QfDV+_c+QFK8>VE-_M4avU7VK zqKP>LQQKN9*iYoq2Gmv*gASBw7nn21t*u?$MhQg}!}&2ggR%KX}v6)*X5R!(<@?obAIOPzRh`-leO%swKh-ar`h@C zR991c5=Tp6v=L|IvXk?!3ZKm^e5h>HIWx(q%F|ywD&L-zZ_Je{-l$V%Le2WxpLhR_ elEULwix}ca>H429OXz{K9WpaAI{mQpbM-fPO-Y&n delta 17 YcmZqiTVb)mhk0`VhX&K;0D&!H065(R!~g&Q diff --git a/indra/newview/installers/windows/lang_pl.nsi b/indra/newview/installers/windows/lang_pl.nsi index 61dc769126811a0a43793b4378b75998fdbf360b..05977847b96a83993a201e58ef3298da74501720 100644 GIT binary patch literal 12080 zcmeI2TW{M&5QSF{L4gAO0eK^W08W6yE&7-~6p8JmZhT37Nzx=hAX~C6Tee)wN@6$t z)p>7wz8$Z3DUl*+J8d2cK^Ico+1Z&hXJ&`|`>!8e<{rDAJ8?sIs^2|*XRhPAZpXFV z$n|yh8~3$aaswTA^xbwxZdd=b_1X1f`})q@9e3CL;a1$bThx1ApKI<<_r}d>cj8(1j#%x_S}7Lz#ocb5 zyEAv7qh2DrEg1tzZ(pn>tRb(>da{mc&Fbj$Omhyj!gJ}Bx%bj+%WLtKj`nNn8tgul z&$qmVgFWzTCfoF6`L16rI5^es5Bkh>w(XAn2(B~~6?tJPCt=;s6Yah!868PNZnXz8 zdFMdaf=@I%*Y~#8I^FWqHNY=OJgzl=>bd;fS)2e)aP5B zC8{>GvL(Hig}QnD#}$iuFX?x+T~e+3-kKp&mW2@F-J+}*nOD` zE%4Ba_gfvWt%^CSJ@&$DNratgB_n;G=#yjgH=bst@OI=cq8!HB({<4rnXn80zSA3? zgSm(9+e9|8itKHT9O#9ek%gtqUibkP%QG8ZK@0rR6=Uz}jqSJH1JCC0&#vZf%P*E` zjOl}Ss(dkX;n!oWU|v#KD>-DK8CbP>weJypqPd%*xQXX1{z8PVYwoIikdL~EK=W5b z-0-vNJ*PNa(`!K(-MD0!t7~5tH~7?IEuXRTD8+|?d&ttnADNqIB}zm7C}+$0iBWS2 zYGdZ8Ug6UVL|L7XN49ZyPoBx9vhSpwrdhR~X3g_1{stf*M&?!QpRa&8qW->m{R1OW{}*dGE1Xwnk~~6+HEiyQe8vcRhAdgE zZ|3uQR}oJn2XEZHtQ!rzk(0}7y!@ITdkMC``Fz%HhWETq*R^lgbLLH0H{hiSt2|V7 z44Y8nUmeS7K7FVi8hMl)+L_AFlT4Co)7-8rn%DXVX+?UI_)RTLAAp=s<~vXnQx&pm z_Gr)iZ|Y5U1c$n2sF!ssGH;&`Q}THosmt}nN~RjuU_zLv;Y z^-_Y2=Q#=0*r5wX*JdP7_T(w{W`-v72RmRqw=X@7^@sZ1^LcALPOy%}iR}%k6Y)NN ztGluo6)!YPl#pN7e64-$y2pH58g#UVxUzH|naj^possKlSSNC4N)a>=dkhs%Bh?Ng z*&DQ+D#H3c-o|y#+;iE={57kXej~ftCtbNuk`>QrTgUp(&IOIFf0gUU05ujWgZKec2KcvOP{GN zytBJ6wkc?x^qX-xm>Ty`SZiSL$Z_m`xldtTK#M;^ymbS26az=XXUsMCBt6Y@_iJH4 z_SVMdSiF!{&z@y$2)myP6=WkrN#ui6U+YrbZZ%=ZYTfI^?u>j47T_4N5%)hrB?H2# zKIlr&Z5;S63RMZ6*7jwbEXy0jfsF?tAOVb6&m*uQ$f1Xi1m-FCFx{GJtQGUetm-Tf zbu*{}XQ`+9>Wh}w4l#d~duLM;KR>!)s8sLZ1LL=RW=gAwLOluq1dQPHNe#twa*j9o|X>&0|LAYBTyC2L#F8FF!P1cN+_ zH?T_;K*Y!DJ#fH#?U-))UW8Qxp+>gIf2DC?#JUw!yVN|kw_<-t)lUZlJwYV3Cdj59 zX1_t*vFe`cGtK(ugIm7CQfz&bRE*A`;rN}0Idx-J#Hb6ZqvL$&#&a^3C$U*-uUMbO z{wuweZ9f9E^R9>ZrWM6B^fa#}z8vJIy8n;4Aq+D;`1)~MNiu*3xtFtF3%56uJ@;90j)$D|L_RH>v<@<`^*%f=D!JcS>(c;r@ z%tb$wOaY$Q$5WRv z9wtT`o(!={FSRbS?C9U{G|ir_qW_s+WxgYd)PWyWwzib(@doo-r-9BJ(kEHlG!9nd zo`pRj!-~UMkU?}<^)=q99gi|bGCLJ!s3GH1H_>zD2%AqN(4P!D`NPX6JnQ0YMRo<< z;KzC+R%7ft>egeO@5!5%$H$*>pc9r_6hG2!N;`HTSEiLziYT6E``BU@Y)6%1bcLRo!m^G(}tQu}RqZ($RSO~ekNLXWdRUidnq^vX~sFQo#6xC z1>Nl0cEv`V-_o@fv2cL#fOR}m4yBVBVmdE3utnYj$SL<&8nbJXn`-}5$LLZ7+k8S(ff)df5DCQq diff --git a/indra/newview/installers/windows/lang_pt-br.nsi b/indra/newview/installers/windows/lang_pt-br.nsi index d481434ab2e136fd3db06efeb848ec44072cef1c..79c2b7b1146bc4e1d2b414b17ec6d8f12a97c539 100644 GIT binary patch delta 1792 zcmbtVO=}ZT6g{jW;v!qO z;r$C&LVtlf7cTq-E?l^GnjPFXs`_Pao@+e_uPB#n-7Jr-ls3q{ol9O3fMv( z73BCXBa2P!(#qmBpSv6_ag4+daty{CViYTs$;&} ze2OixG&CQHx>8a z81e$%<&;B^LAS=1)JOj`MUOB!QJOG>Y3V{Fs diff --git a/indra/newview/installers/windows/lang_ru.nsi b/indra/newview/installers/windows/lang_ru.nsi index d8990fd9553c0deb9bd020015b3d68ca500e9622..0ef1023d886dcb7b520430b4e8d528f434e6d73e 100644 GIT binary patch delta 1850 zcmbtV+iDY06kRc3tY{uYicKqwB_+m7iVvdprHpA>2Xd)RiV8|eld%TUB+aFzzT^)? zIA0+60YZPlZ}0>B64yQ_(`1~f43=Ro`&`!EYwxws{NDQh;YTm7j$`xdCG4Vz8XUf> zC}0PBvN1SyzGT_*KzFiz)gqHr2F`Gdh((WKj%k1saYU7l) zhc?6~?zGV0-oD=3p-&5=xe5Hb=9LfQB}ppl)I~{LMb+mr<2Tx0haOHD(}?drpJGcS zEzL$^o-!AX7EU-PD`t6F=y9%vW8Q7DIN&|NBd+nV8_bqqH@LIQYcSSiPjnE5x_}Qk zWf5f7t+6GwE^>s<=`=R5hWFT}+b+lYgg@lY%}D@~c9ZCf()!%1T1GRq$)HDR)fqya zz(sDCn7w+pwXphhF5;?Owg^Vep5CjX;Rn%WCL!!zHiSHtzQe0P<O02EF>D~5c zR@@&zpw;Jva`A!;#bjG zv4$Zk@I!^LN%`5htlcb^hf%oXrnSlh+1NbeMS${y3HgyEZR~5244JQ{?)b<51_@!2 eE)zl&C}o}=qNeDxe9}?)sIQBuvl~}`-Tebb-cx7* delta 17 ZcmZ1y`^bGm0rTc8jy|T%2LztT0su#_2ZsOv diff --git a/indra/newview/installers/windows/lang_tr.nsi b/indra/newview/installers/windows/lang_tr.nsi index c320764fac4980a9eef5926754ada1370a0e157c..4bb4e14bfa5d049c6239891b544830079bcb2c47 100644 GIT binary patch delta 1854 zcmbtV+iDY06kTbMh)~6Vl~OB1vBaQF@u3v^62>&O1G#9EqJmgrGS)zvq`8$oUwE2;;3|NHI_#UHMpu3Snw#X0(@>n|Cz8Pgf&rOb{(eQ9&mzOxlX-`hH^gLAz_x!6ifL^WEW7Yzd^U$w!q^GwfK*!g|`?SSjh7ODT`V`#5>Sr{r+L0$a;Sgr~_2EkLy-2XiLK-Pc zPt~Xk=}Q?ET}a=F%8cGbg>@~>1qxJl{Bdj#8(79YbskxJH6NS*loIRhEWbzo)QbO8 zSc0wM4>oqgV$L#V(bfZz$xfdr;^Bp*o6}|cnxYxz&&H>#sm_>Taz2^^z1HDbeE1K{ zSjhk__^|>Qt@#KPma=2?WZf02+8Q?_np$yKW#-*Hvj+t delta 29 lcmeB)JLRz$^&{p- zO!xx%6W{#^*E+|colDI`GMURhm$moWd+jrqtH0me9kx%6B;F;vLun%z7BWBfOi*9+6<(r$S~v) zaZ)tp40BvDPRo>I%r)f{cMBvAaQEaH)&$rtl0|G6J3F{~L&fz>1)-S}ypJgpAmeVe z&CGgY0oqbobY)$>$Tr+|FxCb95q56<4S-qKd7hNjwV-H=im43-$52%rA=Cj}#CFCU zl)FV$!HvZlRIXbCt>ZxHRjPL>!Z}byOk)gS@45lxA@W^Z4rEgcT8?47nh-`@lvXvS5YJC&qWor zj@eKRh=NVYQHp|1M~P{%QG!jS%SrO{zZ$dIb$Kk)a>qZ(%sr0>7(SqAy@^ts31yc4 z4-f~jrz~h%32QAaa+EwOH=l?f$lu?-`yj{m^w7Y%kv07%SBI-E(iO{GJeDoBwt%Df zZF+VrX@VreSP6XQLVP?_aa2*Vd76feHLBWToR5uzo^s?bCiW|tw&k0WOCR}au9!;mjXqK~Qr5 delta 17 YcmaFkeaLi!1@q=84jrb=eFAZ!06@Y9ApigX From abf1b6474e0c75131439b6cc7888027d07fe4c7e Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 3 Dec 2018 16:07:27 -0500 Subject: [PATCH 15/38] SL-10153: Update to viewer-manager build 522199 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index a063e4be0e..6aae9561ab 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3138,9 +3138,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 2040ddeb5dd2040f9d57bdc1865af520 + 3504fe5c13ff8ca3bae9de2bfda5d1a5 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28232/230664/viewer_manager-2.0.522096-darwin64-522096.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28374/232934/viewer_manager-2.0.522199-darwin64-522199.tar.bz2 name darwin64 @@ -3162,9 +3162,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - a3c4980f31e3437910b72bd45efb0e6d + d035a93c4d8554241fd43ac91033a838 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28233/230672/viewer_manager-2.0.522096-windows-522096.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28375/232940/viewer_manager-2.0.522199-windows-522199.tar.bz2 name windows @@ -3175,7 +3175,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.522096 + 2.0.522199 vlc-bin From 8205bd22f16c517acbfab1661738176dc158d89b Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 3 Dec 2018 18:59:10 -0500 Subject: [PATCH 16/38] SL-10153: Update to viewer-manager build 522217 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 6aae9561ab..2ebb1cce23 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3138,9 +3138,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 3504fe5c13ff8ca3bae9de2bfda5d1a5 + 7e4fc2b997ff9ef0122e0a56fc765112 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28374/232934/viewer_manager-2.0.522199-darwin64-522199.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28398/233376/viewer_manager-2.0.522217-darwin64-522217.tar.bz2 name darwin64 @@ -3162,9 +3162,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - d035a93c4d8554241fd43ac91033a838 + 998737a96678a7c0881982e884a22d7e url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28375/232940/viewer_manager-2.0.522199-windows-522199.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28399/233382/viewer_manager-2.0.522217-windows-522217.tar.bz2 name windows @@ -3175,7 +3175,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.522199 + 2.0.522217 vlc-bin From 8892ec5a3bb45eeaf3e66cb9ce884f312bfdfe71 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 4 Dec 2018 16:14:32 -0500 Subject: [PATCH 17/38] SL-10153: Update to viewer-manager build 522260 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 2ebb1cce23..953c703886 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3138,9 +3138,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 7e4fc2b997ff9ef0122e0a56fc765112 + 49d8224983843e61b2a770d0e6880c85 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28398/233376/viewer_manager-2.0.522217-darwin64-522217.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28466/235199/viewer_manager-2.0.522260-darwin64-522260.tar.bz2 name darwin64 @@ -3162,9 +3162,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 998737a96678a7c0881982e884a22d7e + 9fc5bf5c63b655f3ed63efd862435926 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28399/233382/viewer_manager-2.0.522217-windows-522217.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28467/235205/viewer_manager-2.0.522260-windows-522260.tar.bz2 name windows @@ -3175,7 +3175,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.522217 + 2.0.522260 vlc-bin From d509e315cfedb1785723184d5f2105af0436eb57 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 5 Dec 2018 10:30:53 -0500 Subject: [PATCH 18/38] DRTVWR-447: Fix BugSplat init with non-ASCII chars in install path. The whole remaining difference between llifstream and std::ifstream is that the former handles UTF-8 coded pathnames. Microsoft's implementation of the latter does not. --- indra/newview/llappviewerwin32.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 75fa3baa42..fff2653c98 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -600,7 +600,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 From 7a336f63cc77a93362f5d4fcc274d1d908ef2f63 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 5 Dec 2018 16:57:00 -0500 Subject: [PATCH 19/38] SL-10153: If $APPDATA isn't already good, try SHGetFolderPath(). In that case, also update $APPDATA for child processes. --- indra/llvfs/lldir_win32.cpp | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp index 9836fa28f2..3e48e086d7 100644 --- a/indra/llvfs/lldir_win32.cpp +++ b/indra/llvfs/lldir_win32.cpp @@ -48,10 +48,38 @@ 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")); + // On Windows, it's a Bad Thing if a pathname contains ASCII question + // marks. In our experience, it means that the original pathname contained + // non-ASCII characters that were munged to '?' somewhere along the way. + // Convert to LLWString first, though, in case one of the bytes in a + // non-ASCII UTF-8 string accidentally resembles '?'. + if (utf8string_to_wstring(mOSUserDir).find(llwchar('?')) != LLWString::npos) + { + // It is really unclear what we should do if the following call fails. + // We use it, among other things, to find where to put our log file! + if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, w_str))) + { + // But of course, only update mOSUserDir if SHGetFolderPathW() works. + mOSUserDir = utf16str_to_utf8str(llutf16string(w_str)); + // Not only that: update our environment so that child processes + // will see a reasonable value as well. Use _putenv_s() rather + // than _wputenv_s() because WE want to control the encoding with + // which APPDATA is passed to child processes, instead of letting + // somebody else pick it. + _putenv_s("APPDATA", mOSUserDir.c_str()); + // SL-10153: It is really tempting to make the above _putenv_s() + // call unconditional, since we've observed cases in which the + // parent viewer receives a valid non-ASCII APPDATA value while + // the child SLVersionChecker process receives one containing + // question marks. But if what we see is already valid, what do we + // gain by storing it again? + } + } // We want cache files to go on the local disk, even if the // user is on a network with a "roaming profile". @@ -63,7 +91,6 @@ LLDir_Win32::LLDir_Win32() // cleans up that version on upgrade. JC mOSCacheDir = ll_safe_string(getenv("LOCALAPPDATA")); - WCHAR w_str[MAX_PATH]; if (GetTempPath(MAX_PATH, w_str)) { if (wcslen(w_str)) /* Flawfinder: ignore */ From 1029f6b776fbef66959ef621f233cf1012b3f72b Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 5 Dec 2018 17:16:06 -0500 Subject: [PATCH 20/38] SL-10153: Update to viewer-manager build 522314 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 953c703886..5f7e22347b 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3138,9 +3138,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 49d8224983843e61b2a770d0e6880c85 + acab355caaab1a5841a200e2d0dd9891 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28466/235199/viewer_manager-2.0.522260-darwin64-522260.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28547/236386/viewer_manager-2.0.522314-darwin64-522314.tar.bz2 name darwin64 @@ -3162,9 +3162,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 9fc5bf5c63b655f3ed63efd862435926 + e649491175876e6bf016a36f97c69497 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28467/235205/viewer_manager-2.0.522260-windows-522260.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28548/236392/viewer_manager-2.0.522314-windows-522314.tar.bz2 name windows @@ -3175,7 +3175,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.522260 + 2.0.522314 vlc-bin From 758e7e8df753a9b63782ff2964c26c0b0a4015fe Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 6 Dec 2018 14:33:51 -0500 Subject: [PATCH 21/38] SL-10174: LOCALAPPDATA bad? Try SHGetFolderPath(CSIDL_LOCAL_APPDATA). This logic is essentially copy-and-edited from the same suspenders-and-belt concerning APPDATA and CSIDL_APPDATA for SL-10153. --- indra/llvfs/lldir_win32.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp index 3e48e086d7..f972f27fd0 100644 --- a/indra/llvfs/lldir_win32.cpp +++ b/indra/llvfs/lldir_win32.cpp @@ -90,6 +90,19 @@ 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")); + // Windows really does not deal well with pathnames containing non-ASCII + // characters. See above remarks about APPDATA. + if (utf8string_to_wstring(mOSCacheDir).find(llwchar('?')) != LLWString::npos) + { + if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, w_str))) + { + // But of course, only update mOSCacheDir if SHGetFolderPathW() works. + mOSCacheDir = utf16str_to_utf8str(llutf16string(w_str)); + // Update our environment so that child processes will see a + // reasonable value as well. + _putenv_s("LOCALAPPDATA", mOSCacheDir.c_str()); + } + } if (GetTempPath(MAX_PATH, w_str)) { From 6e58201736fd3f5a0cdf5a49f2fb8a391ba58222 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sat, 8 Dec 2018 10:25:15 -0500 Subject: [PATCH 22/38] SL-10153: Update to viewer-manager build 522407 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 5f7e22347b..ebda8c791d 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3138,9 +3138,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - acab355caaab1a5841a200e2d0dd9891 + f76807ee2425b1532595bc716456fa6a url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28547/236386/viewer_manager-2.0.522314-darwin64-522314.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28665/237854/viewer_manager-2.0.522407-darwin64-522407.tar.bz2 name darwin64 @@ -3162,9 +3162,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - e649491175876e6bf016a36f97c69497 + 5cb25b4d66f9a8d4f485b7eab7d02ed0 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28548/236392/viewer_manager-2.0.522314-windows-522314.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28666/237860/viewer_manager-2.0.522407-windows-522407.tar.bz2 name windows @@ -3175,7 +3175,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.522314 + 2.0.522407 vlc-bin From a36cd3a2925bf77aa804a5617e0a227cabacde46 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sat, 8 Dec 2018 10:30:18 -0500 Subject: [PATCH 23/38] SL-10153: Try to handle non-English non-ASCII Windows APPDATA. --- indra/llvfs/lldir_win32.cpp | 113 ++++++++++++++++++++++++++++-------- 1 file changed, 89 insertions(+), 24 deletions(-) diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp index f972f27fd0..96bd779b5f 100644 --- a/indra/llvfs/lldir_win32.cpp +++ b/indra/llvfs/lldir_win32.cpp @@ -31,6 +31,8 @@ #include "lldir_win32.h" #include "llerror.h" #include "llrand.h" // for gLindenLabRandomNumber +#include "stringize.h" +#include "llfile.h" #include #include @@ -43,6 +45,48 @@ #define PACKVERSION(major,minor) MAKELONG(minor,major) DWORD GetDllVersion(LPCTSTR lpszDllName); +namespace +{ // anonymous + enum class prst { INIT, OPEN, SKIP } state; + llofstream prelogf; + + void prelog(const std::string& message) + { + switch (state) + { + case prst::INIT: + // assume we failed, until we succeed + state = prst::SKIP; + + // can't initialize within one case of a switch statement + const char* prelog_name; + prelog_name = getenv("PRELOG"); + if (! prelog_name) + // no PRELOG variable set, carry on + return; + prelogf.open(prelog_name, std::ios_base::app); + if (! 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 @@ -52,32 +96,38 @@ LLDir_Win32::LLDir_Win32() // 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")); + // Try using wide-character getenv()?? + wchar_t *APPDATA = _wgetenv(L"APPDATA"); + if (APPDATA) + { + mOSUserDir = ll_convert_wide_to_string(APPDATA, CP_UTF8); + } + PRELOG("APPDATA='" << mOSUserDir << "'"); // On Windows, it's a Bad Thing if a pathname contains ASCII question // marks. In our experience, it means that the original pathname contained // non-ASCII characters that were munged to '?' somewhere along the way. // Convert to LLWString first, though, in case one of the bytes in a // non-ASCII UTF-8 string accidentally resembles '?'. - if (utf8string_to_wstring(mOSUserDir).find(llwchar('?')) != LLWString::npos) + // Bear in mind that llwchar is not necessarily wchar_t, therefore L'?' is + // not necessarily the right type. + if (mOSUserDir.empty() || + utf8string_to_wstring(mOSUserDir).find(llwchar('?')) != LLWString::npos) { - // It is really unclear what we should do if the following call fails. - // We use it, among other things, to find where to put our log file! - if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, w_str))) + PRELOG("APPDATA empty or contains ASCII '?'"); + //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 SHGetFolderPathW() works. - mOSUserDir = utf16str_to_utf8str(llutf16string(w_str)); + // But of course, only update mOSUserDir if SHGetKnownFolderPath() works. + mOSUserDir = ll_convert_wide_to_string(pwstr, CP_UTF8); // Not only that: update our environment so that child processes - // will see a reasonable value as well. Use _putenv_s() rather - // than _wputenv_s() because WE want to control the encoding with - // which APPDATA is passed to child processes, instead of letting - // somebody else pick it. - _putenv_s("APPDATA", mOSUserDir.c_str()); - // SL-10153: It is really tempting to make the above _putenv_s() - // call unconditional, since we've observed cases in which the - // parent viewer receives a valid non-ASCII APPDATA value while - // the child SLVersionChecker process receives one containing - // question marks. But if what we see is already valid, what do we - // gain by storing it again? + // will see a reasonable value as well. + _wputenv_s(L"APPDATA", pwstr); + // SHGetKnownFolderPath() contract requires us to free pwstr + CoTaskMemFree(pwstr); + PRELOG("mOSUserDir='" << mOSUserDir << "'"); } } @@ -89,18 +139,33 @@ 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")); + // Again, try using wide-character getenv(). + wchar_t *LOCALAPPDATA = _wgetenv(L"LOCALAPPDATA"); + if (LOCALAPPDATA) + { + mOSCacheDir = ll_convert_wide_to_string(LOCALAPPDATA, CP_UTF8); + } + PRELOG("LOCALAPPDATA='" << mOSCacheDir << "'"); // Windows really does not deal well with pathnames containing non-ASCII // characters. See above remarks about APPDATA. - if (utf8string_to_wstring(mOSCacheDir).find(llwchar('?')) != LLWString::npos) + if (mOSCacheDir.empty() || + utf8string_to_wstring(mOSCacheDir).find(llwchar('?')) != LLWString::npos) { - if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, w_str))) + PRELOG("LOCALAPPDATA empty or contains ASCII '?'"); + //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 SHGetFolderPathW() works. - mOSCacheDir = utf16str_to_utf8str(llutf16string(w_str)); + // But of course, only update mOSCacheDir if SHGetKnownFolderPath() works. + mOSCacheDir = ll_convert_wide_to_string(pwstr, CP_UTF8); // Update our environment so that child processes will see a // reasonable value as well. - _putenv_s("LOCALAPPDATA", mOSCacheDir.c_str()); + _wputenv_s(L"LOCALAPPDATA", pwstr); + // SHGetKnownFolderPath() contract requires us to free pwstr + CoTaskMemFree(pwstr); + PRELOG("mOSCacheDir='" << mOSCacheDir << "'"); } } From a4eb5056a717feaf940f125756c7521b9103d41a Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sat, 8 Dec 2018 11:26:37 -0500 Subject: [PATCH 24/38] SL-10153: Need ole32 for new Windows call to CoTaskMemFree(). --- indra/llvfs/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/indra/llvfs/CMakeLists.txt b/indra/llvfs/CMakeLists.txt index 67dce8c073..8578f7a6bd 100644 --- a/indra/llvfs/CMakeLists.txt +++ b/indra/llvfs/CMakeLists.txt @@ -98,6 +98,9 @@ if (LL_TESTS) # INTEGRATION TESTS set(test_libs llmath llcommon llvfs ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES}) + if (WINDOWS) + list(APPEND test_libs ole32) + endif (WINDOWS) # TODO: Some of these need refactoring to be proper Unit tests rather than Integration tests. LL_ADD_INTEGRATION_TEST(lldir "" "${test_libs}") From 601cbe1f60b94ae8105329b4e4f745b36721e5aa Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sat, 8 Dec 2018 12:18:46 -0500 Subject: [PATCH 25/38] SL-10153: Add ole32 to WINDOWS_LIBRARIES so it's everywhere we need. --- indra/cmake/Linking.cmake | 1 + indra/llvfs/CMakeLists.txt | 3 --- indra/newview/CMakeLists.txt | 1 - indra/win_crash_logger/CMakeLists.txt | 1 - 4 files changed, 1 insertion(+), 5 deletions(-) diff --git a/indra/cmake/Linking.cmake b/indra/cmake/Linking.cmake index 74fe3f1137..3cb235a9d5 100644 --- a/indra/cmake/Linking.cmake +++ b/indra/cmake/Linking.cmake @@ -66,6 +66,7 @@ if (WINDOWS) wldap32 gdi32 user32 + ole32 dbghelp ) else (WINDOWS) diff --git a/indra/llvfs/CMakeLists.txt b/indra/llvfs/CMakeLists.txt index 8578f7a6bd..67dce8c073 100644 --- a/indra/llvfs/CMakeLists.txt +++ b/indra/llvfs/CMakeLists.txt @@ -98,9 +98,6 @@ if (LL_TESTS) # INTEGRATION TESTS set(test_libs llmath llcommon llvfs ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES}) - if (WINDOWS) - list(APPEND test_libs ole32) - endif (WINDOWS) # TODO: Some of these need refactoring to be proper Unit tests rather than Integration tests. LL_ADD_INTEGRATION_TEST(lldir "" "${test_libs}") diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index f10b54d73c..99f99834f3 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1585,7 +1585,6 @@ if (WINDOWS) kernel32 odbc32 odbccp32 - ole32 oleaut32 shell32 Vfw32 diff --git a/indra/win_crash_logger/CMakeLists.txt b/indra/win_crash_logger/CMakeLists.txt index 144d037a31..4fba26ab2f 100644 --- a/indra/win_crash_logger/CMakeLists.txt +++ b/indra/win_crash_logger/CMakeLists.txt @@ -89,7 +89,6 @@ target_link_libraries(windows-crash-logger ${GOOGLE_PERFTOOLS_LIBRARIES} user32 gdi32 - ole32 oleaut32 wininet Wldap32 From 73eadfa12a23ed5e2e47c208f18795061caff6f3 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 10 Dec 2018 17:11:40 -0500 Subject: [PATCH 26/38] INTL-318: Stop processing Danish and Polish language files. --- indra/newview/installers/windows/installer_template.nsi | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi index b2d376d0c0..9a304559e1 100644 --- a/indra/newview/installers/windows/installer_template.nsi +++ b/indra/newview/installers/windows/installer_template.nsi @@ -51,27 +51,28 @@ RequestExecutionLevel highest # match MULTIUSER_EXECUTIONLEVEL ;; en-us as first language file." !include "%%SOURCE%%\installers\windows\lang_en-us.nsi" -!include "%%SOURCE%%\installers\windows\lang_da.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" From 9479d422d4b34e2ffd08017272412ab3bd1ae00e Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 10 Dec 2018 17:14:31 -0500 Subject: [PATCH 27/38] SL-10153: Use a degenerate singleton for PRELOG log file. The previous build declared a static std::ofstream; but the code that determines the pathname for the log file is called so early that static objects have not yet been constructed. Declare a pointer instead, and instantiate it on demand. --- indra/llvfs/lldir_win32.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp index 96bd779b5f..e97424c9a9 100644 --- a/indra/llvfs/lldir_win32.cpp +++ b/indra/llvfs/lldir_win32.cpp @@ -30,7 +30,6 @@ #include "lldir_win32.h" #include "llerror.h" -#include "llrand.h" // for gLindenLabRandomNumber #include "stringize.h" #include "llfile.h" #include @@ -47,8 +46,10 @@ DWORD GetDllVersion(LPCTSTR lpszDllName); namespace { // anonymous - enum class prst { INIT, OPEN, SKIP } state; - llofstream prelogf; + 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) { @@ -64,18 +65,18 @@ namespace if (! prelog_name) // no PRELOG variable set, carry on return; - prelogf.open(prelog_name, std::ios_base::app); - if (! prelogf.is_open()) + prelogf = new std::ofstream(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; + (*prelogf) << "========================================================================" + << std::endl; // fall through, don't break case prst::OPEN: - prelogf << message << std::endl; + (*prelogf) << message << std::endl; break; case prst::SKIP: From 63d601679168d0bf8de2600bb74e435f54096b9a Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 11 Dec 2018 09:06:41 -0500 Subject: [PATCH 28/38] SL-10153: Update to viewer-manager build 522443 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index ebda8c791d..f646843086 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3138,9 +3138,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - f76807ee2425b1532595bc716456fa6a + 9ff6f24f703663e82489253c0a1fae8a url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28665/237854/viewer_manager-2.0.522407-darwin64-522407.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28732/238505/viewer_manager-2.0.522443-darwin64-522443.tar.bz2 name darwin64 @@ -3162,9 +3162,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 5cb25b4d66f9a8d4f485b7eab7d02ed0 + 6e9d92a0810619377dd8f3dccee9e594 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28666/237860/viewer_manager-2.0.522407-windows-522407.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28731/238511/viewer_manager-2.0.522443-windows-522443.tar.bz2 name windows @@ -3175,7 +3175,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.522407 + 2.0.522443 vlc-bin From d72dd8a35dadefb816ad29bb9e41559fa288679a Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 11 Dec 2018 15:47:17 -0500 Subject: [PATCH 29/38] SL-10153: Update to viewer-manager build 522465 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index f646843086..ddf07016ae 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3138,9 +3138,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 9ff6f24f703663e82489253c0a1fae8a + cf01ec13d504668201fe820ea2289024 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28732/238505/viewer_manager-2.0.522443-darwin64-522443.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28777/239560/viewer_manager-2.0.522465-darwin64-522465.tar.bz2 name darwin64 @@ -3162,9 +3162,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 6e9d92a0810619377dd8f3dccee9e594 + f6c99e3647a5eb01292d0a2362131869 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28731/238511/viewer_manager-2.0.522443-windows-522443.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28776/239566/viewer_manager-2.0.522465-windows-522465.tar.bz2 name windows @@ -3175,7 +3175,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.522443 + 2.0.522465 vlc-bin From bb4a649b9c324e7989de6e59398c85e80fe2acc7 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 11 Dec 2018 15:47:29 -0500 Subject: [PATCH 30/38] SL-10153: Validate APPDATA, LOCALAPPDATA by checking existence. --- indra/llvfs/lldir_win32.cpp | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp index e97424c9a9..fc4680bbfb 100644 --- a/indra/llvfs/lldir_win32.cpp +++ b/indra/llvfs/lldir_win32.cpp @@ -104,17 +104,13 @@ LLDir_Win32::LLDir_Win32() mOSUserDir = ll_convert_wide_to_string(APPDATA, CP_UTF8); } PRELOG("APPDATA='" << mOSUserDir << "'"); - // On Windows, it's a Bad Thing if a pathname contains ASCII question - // marks. In our experience, it means that the original pathname contained - // non-ASCII characters that were munged to '?' somewhere along the way. - // Convert to LLWString first, though, in case one of the bytes in a - // non-ASCII UTF-8 string accidentally resembles '?'. - // Bear in mind that llwchar is not necessarily wchar_t, therefore L'?' is - // not necessarily the right type. - if (mOSUserDir.empty() || - utf8string_to_wstring(mOSUserDir).find(llwchar('?')) != LLWString::npos) + // 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 empty or contains ASCII '?'"); + 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); @@ -149,10 +145,9 @@ LLDir_Win32::LLDir_Win32() PRELOG("LOCALAPPDATA='" << mOSCacheDir << "'"); // Windows really does not deal well with pathnames containing non-ASCII // characters. See above remarks about APPDATA. - if (mOSCacheDir.empty() || - utf8string_to_wstring(mOSCacheDir).find(llwchar('?')) != LLWString::npos) + if (mOSCacheDir.empty() || ! fileExists(mOSCacheDir)) { - PRELOG("LOCALAPPDATA empty or contains ASCII '?'"); + 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); From 4e894eb2a7ed6651c54890cd20106bfacd61ef0a Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 11 Dec 2018 20:48:20 -0500 Subject: [PATCH 31/38] SL-10153: Improve ll_convert_string_to_wide() and its converse. Instead of returning a wchar_t* and requiring the caller to delete it later, return a std::basic_string that's self-cleaning. If the caller wants a wchar_t*, s/he can call c_str() on the returned string. Default the code_page parameter to CP_UTF8, since we try to be really consistent about using UTF-8 encoding for all our internal std::strings. --- indra/llcommon/llstring.cpp | 32 ++++++++++++++++++++++---------- indra/llcommon/llstring.h | 10 ++++++---- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 9a02fecd72..42390c8a7b 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -30,6 +30,7 @@ #include "llerror.h" #include "llfasttimer.h" #include "llsd.h" +#include #if LL_WINDOWS #include "llwin32headerslean.h" @@ -672,6 +673,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; @@ -709,7 +715,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::basic_string ll_convert_string_to_wide(const std::string& in) +{ + return ll_convert_string_to_wide(in, CP_UTF8); +} + +std::basic_string 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, @@ -719,24 +730,25 @@ 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 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 from our temporary output buffer + return {&w_out[0]}; } 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; } diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 68ee9db46b..7c3e9f952d 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -635,16 +635,18 @@ 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 /** * 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::basic_string ll_convert_string_to_wide(const std::string& in, + unsigned int code_page); +LL_COMMON_API std::basic_string ll_convert_string_to_wide(const std::string& in); + // default CP_UTF8 /** - * Converts incoming string into urf8 string + * Converts incoming string into utf8 string * */ LL_COMMON_API std::string ll_convert_string_to_utf8_string(const std::string& in); From 02b9ac8d9a349b757a426842b5125057d11c0bbb Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 11 Dec 2018 20:51:51 -0500 Subject: [PATCH 32/38] SL-10153: Fix OSMessageBoxWin32() to handle non-ASCII text. --- indra/llwindow/llwindowwin32.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 4ee4a5357c..504c1589b0 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -3275,8 +3275,10 @@ S32 OSMessageBoxWin32(const std::string& text, const std::string& caption, U32 t break; } - // HACK! Doesn't properly handle wide strings! - int retval_win = MessageBoxA(NULL, text.c_str(), caption.c_str(), uType); + 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) From cbf4295b63fcc7128f928d1718efe069a9f3a789 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 13 Dec 2018 12:02:38 -0500 Subject: [PATCH 33/38] SL-10153: Update to viewer-manager build 522507 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index ddf07016ae..3b4eb2cd87 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3138,9 +3138,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - cf01ec13d504668201fe820ea2289024 + e2bef561238448fe512146baa6dacabc url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28777/239560/viewer_manager-2.0.522465-darwin64-522465.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28859/240421/viewer_manager-2.0.522507-darwin64-522507.tar.bz2 name darwin64 @@ -3162,9 +3162,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - f6c99e3647a5eb01292d0a2362131869 + 75cdf1afc293423553b6d190ce422412 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28776/239566/viewer_manager-2.0.522465-windows-522465.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/28858/240427/viewer_manager-2.0.522507-windows-522507.tar.bz2 name windows @@ -3175,7 +3175,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.522465 + 2.0.522507 vlc-bin From 9ffcafb64b4483c315d00e88ffc1438bce1f7915 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 14 Dec 2018 10:48:43 -0500 Subject: [PATCH 34/38] SL-10153: Introduce ll_convert, windows_message() templates. Add ll_convert template, used as (e.g.): ll_convert(value_of_some_other_string_type); There is no generic template implementation -- the template exists solely to provide generic aliases for a bewildering family of llstring.h string- conversion functions with highly-specific names. There's a generic implementation, though, for the degenerate case where FROM and TO are identical. Add ll_convert<> specialization aliases for most of the string-conversion functions declared in llstring.h, including the Windows-specific ones involving llutf16string and std::wstring. Add a mini-lecture in llstring.h about appropriate use of string types on Windows. Add LL_WCHAR_T_NATIVE llpreprocessor.h macro so we can detect whether to provide separate conversions for llutf16string and std::wstring, or whether those would collide because the types are identical. Add inline ll_convert_wide_to_string(const std::wstring&) overloads so caller isn't required to call arg.c_str(), which naturally permits an ll_convert alias. Add ll_convert_wide_to_wstring(), ll_convert_wstring_to_wide() as placeholders for converting between Windows std::wstring and Linden LLWString, with corresponding ll_convert aliases. We don't yet have library code to perform such conversions officially; for now, just copy characters. Add LLStringUtil::getenv(key) and getoptenv(key) functions. The latter returns boost::optional in case the caller needs to detect absence of a given environment variable rather than simply accepting a default value. Naturally getenv(), which accepts a default, is implemented using getoptenv(). getoptenv(), in turn, is implemented using an underlying llstring_getoptenv(). On Windows, llstring_getoptenv() returns boost::optional (based on GetEnvironmentVariableW()), whereas elsewhere, llstring_getoptenv() returns boost::optional (based on classic Posix getenv()). The beauty of generic ll_convert is that the portable LLStringUtilBase:: getoptenv() template can call the platform-specific llstring_getoptenv() and transparently perform whatever conversion is necessary to return the desired string_type. Add windows_message(error) template, with an overload that implicitly calls GetLastError(). We provide a single concrete windows_message() implementation because that's what we get from Windows FormatMessageW() -- everything else is a generic conversion to the desired target string type. This obviates llprocess.cpp's previous WindowsErrorString() implementation -- reimplement using windows_message(). --- indra/llcommon/llpreprocessor.h | 21 ++++ indra/llcommon/llprocess.cpp | 27 +---- indra/llcommon/llstring.cpp | 125 ++++++++++++++++++++++- indra/llcommon/llstring.h | 176 +++++++++++++++++++++++++++++++- indra/llcommon/stdtypes.h | 7 +- 5 files changed, 323 insertions(+), 33 deletions(-) diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index ef015fdce4..e8f9981437 100644 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h @@ -101,6 +101,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 @@ -177,6 +180,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 diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp index 5753efdc59..1fa53f322b 100644 --- a/indra/llcommon/llprocess.cpp +++ b/indra/llcommon/llprocess.cpp @@ -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(result)); } /***************************************************************************** diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 42390c8a7b..f931103ba6 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -53,6 +53,40 @@ std::string ll_safe_string(const char* in, S32 maxlen) return std::string(); } +boost::optional 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 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 { &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(last_error) << LL_ENDL; + } + // return empty boost::optional + return {}; +} + bool is_char_hex(char hex) { if((hex >= '0') && (hex <= '9')) @@ -715,12 +749,12 @@ std::string ll_convert_wide_to_string(const wchar_t* in, unsigned int code_page) return out; } -std::basic_string ll_convert_string_to_wide(const std::string& in) +std::wstring ll_convert_string_to_wide(const std::string& in) { return ll_convert_string_to_wide(in, CP_UTF8); } -std::basic_string ll_convert_string_to_wide(const std::string& in, unsigned int code_page) +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, @@ -745,6 +779,24 @@ std::basic_string ll_convert_string_to_wide(const std::string& in, unsi 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) { auto w_mesg = ll_convert_string_to_wide(in, CP_ACP); @@ -752,7 +804,74 @@ std::string ll_convert_string_to_utf8_string(const std::string& in) 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(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 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(); +} + +#else // ! LL_WINDOWS + +boost::optional llstring_getoptenv(const std::string& key) +{ + auto found = getenv(key.c_str()); + if (found) + { + // return populated boost::optional + return { found }; + } + else + { + // return empty boost::optional + return {}; + } +} + +#endif // ! LL_WINDOWS long LLStringOps::sPacificTimeOffset = 0; long LLStringOps::sLocalTimeOffset = 0; diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 7c3e9f952d..2dccc7cbdf 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -27,6 +27,7 @@ #ifndef LL_LLSTRING_H #define LL_LLSTRING_H +#include #include #include //#include @@ -337,6 +338,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 getoptenv(const std::string& key); + static void addCRLF(string_type& string); static void removeCRLF(string_type& string); static void removeWindowsCR(string_type& string); @@ -496,6 +510,37 @@ LL_COMMON_API bool iswindividual(llwchar elem); * Unicode support */ +/// generic conversion aliases +template +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(from_value) API. +template +TO ll_convert(const FROM& in) +{ + return ll_convert_impl()(in); +} + +// degenerate case +template +struct ll_convert_impl +{ + T operator()(const T& in) const { return in; } +}; + +// specialize ll_convert_impl to return EXPR +#define ll_convert_alias(TO, FROM, EXPR) \ +template<> \ +struct ll_convert_impl \ +{ \ + 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. @@ -503,30 +548,83 @@ 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 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 +// 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) + +// converting between std::wstring and llutf16string involves copying chars +// enclose the brace-initialization expression in parens to protect the comma +// from macro-argument parsing +ll_convert_alias(llutf16string, std::wstring, ({ in.begin(), in.end() })); +ll_convert_alias(std::wstring, llutf16string, ({ in.begin(), in.end() })); +#endif + 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);} @@ -636,14 +734,36 @@ using snprintf_hack::snprintf; */ 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. */ -LL_COMMON_API std::basic_string ll_convert_string_to_wide(const std::string& in, - unsigned int code_page); -LL_COMMON_API std::basic_string ll_convert_string_to_wide(const std::string& in); - // default CP_UTF8 +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)); + +/** + * 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 @@ -651,8 +771,39 @@ LL_COMMON_API std::basic_string ll_convert_string_to_wide(const std::st */ 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 +STRING windows_message(unsigned long error) +{ + return ll_convert(windows_message(error)); +} + +/// There's only one real implementation +template<> +LL_COMMON_API std::wstring windows_message(unsigned long error); + +/// Get Windows message string, implicitly calling GetLastError() +template +STRING windows_message() { return windows_message(GetLastError()); } + //@} -#endif // LL_WINDOWS + +LL_COMMON_API boost::optional llstring_getoptenv(const std::string& key); + +#else // ! LL_WINDOWS + +LL_COMMON_API boost::optional llstring_getoptenv(const std::string& key); + +#endif // ! LL_WINDOWS /** * Many of the 'strip' and 'replace' methods of LLStringUtilBase need @@ -1595,6 +1746,21 @@ bool LLStringUtilBase::endsWith( return (idx == (string.size() - substr.size())); } +// static +template +auto LLStringUtilBase::getoptenv(const std::string& key) -> boost::optional +{ + auto found{llstring_getoptenv(key)}; + return found? { ll_convert(*found) } : {}; +} + +// static +template +auto LLStringUtilBase::getenv(const std::string& key, const string_type& dflt) -> string_type +{ + auto found{getoptenv(key)}; + return found? *found : dflt; +} template BOOL LLStringUtilBase::convertToBOOL(const string_type& string, BOOL& value) diff --git a/indra/llcommon/stdtypes.h b/indra/llcommon/stdtypes.h index bf3f3f9ee8..6c9871e76c 100644 --- a/indra/llcommon/stdtypes.h +++ b/indra/llcommon/stdtypes.h @@ -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; From 132e708fec50fd756b822925313456c70a4ff27f Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 14 Dec 2018 12:01:51 -0500 Subject: [PATCH 35/38] SL-10153: Fix previous commit for non-Windows systems. Move Windows-flavored llstring_getoptenv() to Windows-specific section of llstring.cpp. boost::optional type must be stated explicitly to initialize with a value. On platforms where llwchar is the same as wchar_t, LLWString is the same as std::wstring, so ll_convert specializations for std::wstring would duplicate those for LLWString. Defend against that. The compilers we use don't like 'return condition? { expr } : {}', in which we hope to construct and return an instance of the declared return type without having to restate the type. It works to use an explicit 'if' statement. --- indra/llcommon/llstring.cpp | 70 ++++++++++++++++++------------------- indra/llcommon/llstring.h | 30 +++++++++++----- 2 files changed, 57 insertions(+), 43 deletions(-) diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index f931103ba6..0174c411b4 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -53,40 +53,6 @@ std::string ll_safe_string(const char* in, S32 maxlen) return std::string(); } -boost::optional 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 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 { &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(last_error) << LL_ENDL; - } - // return empty boost::optional - return {}; -} - bool is_char_hex(char hex) { if((hex >= '0') && (hex <= '9')) @@ -854,6 +820,40 @@ std::wstring windows_message(DWORD error) return out.str(); } +boost::optional 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 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(&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(last_error) << LL_ENDL; + } + // return empty boost::optional + return {}; +} + #else // ! LL_WINDOWS boost::optional llstring_getoptenv(const std::string& key) @@ -862,7 +862,7 @@ boost::optional llstring_getoptenv(const std::string& key) if (found) { // return populated boost::optional - return { found }; + return boost::optional(found); } else { diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 2dccc7cbdf..87cb35c59c 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -583,19 +583,24 @@ typedef std::basic_string llutf16string; // 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 +#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) -// converting between std::wstring and llutf16string involves copying chars -// enclose the brace-initialization expression in parens to protect the comma -// from macro-argument parsing -ll_convert_alias(llutf16string, std::wstring, ({ in.begin(), in.end() })); -ll_convert_alias(std::wstring, llutf16string, ({ in.begin(), in.end() })); -#endif +#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); @@ -1751,7 +1756,16 @@ template auto LLStringUtilBase::getoptenv(const std::string& key) -> boost::optional { auto found{llstring_getoptenv(key)}; - return found? { ll_convert(*found) } : {}; + if (found) + { + // return populated boost::optional + return { ll_convert(*found) }; + } + else + { + // empty boost::optional + return {}; + } } // static From c4096f670c7b3d43f8a5c1f65ef7e02033b0329d Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 14 Dec 2018 15:38:13 -0500 Subject: [PATCH 36/38] SL-10153: Review and rationalize fetching paths from environment. Use LLStringUtil::getenv() or getoptenv() whenever we fetch a string that will be used as a pathname. Use LLFile::tmpdir() instead of getenv("TEMP"). As an added extra-special bonus, finally clean up $TMP/llcontrol-test-zzzzzz directories that have been accumulating every time we run a local build! --- indra/llcommon/llfile.cpp | 19 ++++--- indra/llcommon/tests/llleap_test.cpp | 7 ++- indra/llcommon/tests/llprocess_test.cpp | 5 +- indra/llcommon/tests/llsdserialize_test.cpp | 7 +-- indra/llmessage/tests/commtest.h | 8 +-- indra/llmessage/tests/llhttpclient_test.cpp | 9 ++-- indra/llrender/llfontgl.cpp | 39 ++++++-------- indra/llvfs/lldir_linux.cpp | 33 ++++++------ indra/llvfs/lldir_solaris.cpp | 60 +++++++++------------ indra/llvfs/lldir_win32.cpp | 26 +++++---- indra/llxml/tests/llcontrol_test.cpp | 39 ++++++-------- indra/newview/llexternaleditor.cpp | 7 +-- indra/newview/llwebprofile.cpp | 4 +- 13 files changed, 115 insertions(+), 148 deletions(-) diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp index fc203f78e1..8355b1e797 100644 --- a/indra/llcommon/llfile.cpp +++ b/indra/llcommon/llfile.cpp @@ -30,6 +30,7 @@ #if LL_WINDOWS #include "llwin32headerslean.h" #include // Windows errno +#include #else #include #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'"; } @@ -341,17 +344,13 @@ const char *LLFile::tmpdir() #if LL_WINDOWS sep = '\\'; - DWORD len = GetTempPathW(0, L""); - llutf16string utf16path; - utf16path.resize(len + 1); - len = GetTempPathW(static_cast(utf16path.size()), &utf16path[0]); - utf8path = utf16str_to_utf8str(utf16path); + std::vector 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) { diff --git a/indra/llcommon/tests/llleap_test.cpp b/indra/llcommon/tests/llleap_test.cpp index c387da6c48..45648536c4 100644 --- a/indra/llcommon/tests/llleap_test.cpp +++ b/indra/llcommon/tests/llleap_test.cpp @@ -26,6 +26,7 @@ #include "wrapllerrs.h" #include "llevents.h" #include "llprocess.h" +#include "llstring.h" #include "stringize.h" #include "StringVec.h" #include @@ -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_group; diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp index b27e125d2e..5c87cdabd9 100644 --- a/indra/llcommon/tests/llprocess_test.cpp +++ b/indra/llcommon/tests/llprocess_test.cpp @@ -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; diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp index 745e3a168c..6ac974e659 100644 --- a/indra/llcommon/tests/llsdserialize_test.cpp +++ b/indra/llcommon/tests/llsdserialize_test.cpp @@ -41,6 +41,7 @@ typedef U32 uint32_t; #include #include #include "llprocess.h" +#include "llstring.h" #endif #include "boost/range.hpp" @@ -1705,8 +1706,8 @@ namespace tut template 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]; diff --git a/indra/llmessage/tests/commtest.h b/indra/llmessage/tests/commtest.h index 7c8f27bbd2..0359eba803 100644 --- a/indra/llmessage/tests/commtest.h +++ b/indra/llmessage/tests/commtest.h @@ -34,6 +34,7 @@ #include "llsd.h" #include "llhost.h" #include "llexception.h" +#include "llstring.h" #include "stringize.h" #include #include @@ -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")); } diff --git a/indra/llmessage/tests/llhttpclient_test.cpp b/indra/llmessage/tests/llhttpclient_test.cpp index 9356a14f1f..78faa66a0d 100644 --- a/indra/llmessage/tests/llhttpclient_test.cpp +++ b/indra/llmessage/tests/llhttpclient_test.cpp @@ -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: diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index cf0a117567..bb56988422 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -1063,33 +1063,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 {}; } diff --git a/indra/llvfs/lldir_linux.cpp b/indra/llvfs/lldir_linux.cpp index 2cd06b81f8..80ad05345a 100644 --- a/indra/llvfs/lldir_linux.cpp +++ b/indra/llvfs/lldir_linux.cpp @@ -29,6 +29,7 @@ #include "lldir_linux.h" #include "llerror.h" #include "llrand.h" +#include "llstring.h" #include #include #include @@ -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 { diff --git a/indra/llvfs/lldir_solaris.cpp b/indra/llvfs/lldir_solaris.cpp index d3536a12ee..f18560ff20 100644 --- a/indra/llvfs/lldir_solaris.cpp +++ b/indra/llvfs/lldir_solaris.cpp @@ -29,6 +29,7 @@ #include "lldir_solaris.h" #include "llerror.h" #include "llrand.h" +#include "llstring.h" #include #include #include @@ -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 { diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp index fc4680bbfb..acf734f16b 100644 --- a/indra/llvfs/lldir_win32.cpp +++ b/indra/llvfs/lldir_win32.cpp @@ -30,6 +30,7 @@ #include "lldir_win32.h" #include "llerror.h" +#include "llstring.h" #include "stringize.h" #include "llfile.h" #include @@ -55,17 +56,17 @@ namespace { switch (state) { + boost::optional prelog_name; + case prst::INIT: // assume we failed, until we succeed state = prst::SKIP; - // can't initialize within one case of a switch statement - const char* prelog_name; - prelog_name = getenv("PRELOG"); + prelog_name = LLDirUtil::getoptenv("PRELOG"); if (! prelog_name) // no PRELOG variable set, carry on return; - prelogf = new std::ofstream(prelog_name, std::ios_base::app); + prelogf = new llofstream(*prelog_name, std::ios_base::app); if (! (prelogf && prelogf->is_open())) // can't complain to anybody; how? return; @@ -95,13 +96,11 @@ LLDir_Win32::LLDir_Win32() 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). - // Try using wide-character getenv()?? - wchar_t *APPDATA = _wgetenv(L"APPDATA"); + // correct. + auto APPDATA = LLStringUtil::getoptenv("APPDATA"); if (APPDATA) { - mOSUserDir = ll_convert_wide_to_string(APPDATA, CP_UTF8); + mOSUserDir = *APPDATA; } PRELOG("APPDATA='" << mOSUserDir << "'"); // On Windows, we could have received a plain-ASCII pathname in which @@ -118,7 +117,7 @@ LLDir_Win32::LLDir_Win32() if (SUCCEEDED(okay) && pwstr) { // But of course, only update mOSUserDir if SHGetKnownFolderPath() works. - mOSUserDir = ll_convert_wide_to_string(pwstr, CP_UTF8); + 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); @@ -136,11 +135,10 @@ LLDir_Win32::LLDir_Win32() // // We used to store the cache in AppData\Roaming, and the installer // cleans up that version on upgrade. JC - // Again, try using wide-character getenv(). - wchar_t *LOCALAPPDATA = _wgetenv(L"LOCALAPPDATA"); + auto LOCALAPPDATA = LLStringUtil::getoptenv("LOCALAPPDATA"); if (LOCALAPPDATA) { - mOSCacheDir = ll_convert_wide_to_string(LOCALAPPDATA, CP_UTF8); + mOSCacheDir = *LOCALAPPDATA; } PRELOG("LOCALAPPDATA='" << mOSCacheDir << "'"); // Windows really does not deal well with pathnames containing non-ASCII @@ -155,7 +153,7 @@ LLDir_Win32::LLDir_Win32() if (SUCCEEDED(okay) && pwstr) { // But of course, only update mOSCacheDir if SHGetKnownFolderPath() works. - mOSCacheDir = ll_convert_wide_to_string(pwstr, CP_UTF8); + 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); diff --git a/indra/llxml/tests/llcontrol_test.cpp b/indra/llxml/tests/llcontrol_test.cpp index 2b691ffbb1..f7e43d6def 100644 --- a/indra/llxml/tests/llcontrol_test.cpp +++ b/indra/llxml/tests/llcontrol_test.cpp @@ -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 +#include namespace tut { - struct control_group { - LLControlGroup* mCG; + std::unique_ptr mCG; std::string mTestConfigDir; std::string mTestConfigFile; + std::vector 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); } } diff --git a/indra/newview/llexternaleditor.cpp b/indra/newview/llexternaleditor.cpp index df9c848cb8..776bbf78c2 100644 --- a/indra/newview/llexternaleditor.cpp +++ b/indra/newview/llexternaleditor.cpp @@ -31,6 +31,7 @@ #include "llui.h" #include "llprocess.h" #include "llsdutil.h" +#include "llstring.h" #include // static @@ -188,12 +189,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; } } diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp index 81d4e30a7a..8dcef2c7cd 100644 --- a/indra/newview/llwebprofile.cpp +++ b/indra/newview/llwebprofile.cpp @@ -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); } From 3c53f8abded5da7e9743b743170538a1ede5635a Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 14 Dec 2018 16:00:09 -0500 Subject: [PATCH 37/38] SL-10153: VS 2013 isn't so fond of ?: involving std::string. --- indra/llcommon/llstring.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 87cb35c59c..8d2c8d79d7 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -1773,7 +1773,14 @@ template auto LLStringUtilBase::getenv(const std::string& key, const string_type& dflt) -> string_type { auto found{getoptenv(key)}; - return found? *found : dflt; + if (found) + { + return *found; + } + else + { + return dflt; + } } template From 4a136572857fcf5d5fd21789a777bbde67c1076d Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sat, 15 Dec 2018 09:13:24 -0500 Subject: [PATCH 38/38] SL-10153: auto name{expression} declares an initializer_list instead of a variable of type decltype(expression). Using SHGetKnownFolderPath(FOLDERID_Fonts) in LLFontGL::getFontPathSystem() requires new Windows #include files. A variable with a constructor can't be declared within the braces of a switch statement, even outside any of its case clauses. --- indra/llcommon/llstring.h | 4 ++-- indra/llrender/llfontgl.cpp | 6 ++++++ indra/llvfs/lldir_win32.cpp | 6 +++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 8d2c8d79d7..30bec3a6f8 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -1755,7 +1755,7 @@ bool LLStringUtilBase::endsWith( template auto LLStringUtilBase::getoptenv(const std::string& key) -> boost::optional { - auto found{llstring_getoptenv(key)}; + auto found(llstring_getoptenv(key)); if (found) { // return populated boost::optional @@ -1772,7 +1772,7 @@ auto LLStringUtilBase::getoptenv(const std::string& key) -> boost::optional auto LLStringUtilBase::getenv(const std::string& key, const string_type& dflt) -> string_type { - auto found{getoptenv(key)}; + auto found(getoptenv(key)); if (found) { return *found; diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index bb56988422..9b43680949 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -44,6 +44,12 @@ // Third party library includes #include +#if LL_WINDOWS +#include +#include +#include +#endif // LL_WINDOWS + const S32 BOLD_OFFSET = 1; // static class members diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp index acf734f16b..b3b3afb37e 100644 --- a/indra/llvfs/lldir_win32.cpp +++ b/indra/llvfs/lldir_win32.cpp @@ -54,15 +54,15 @@ namespace void prelog(const std::string& message) { + boost::optional prelog_name; + switch (state) { - boost::optional prelog_name; - case prst::INIT: // assume we failed, until we succeed state = prst::SKIP; - prelog_name = LLDirUtil::getoptenv("PRELOG"); + prelog_name = LLStringUtil::getoptenv("PRELOG"); if (! prelog_name) // no PRELOG variable set, carry on return;