How to request plain HTTP from a website using Inetc - nsis

Haya, at the moment im trying to solve a problem in my code regarding a SendRequest error since i believe the website im using (https://www.gnu.org/licenses/gpl-3.0.txt) is not being validated as having a correct certificate by inetc or something close to this - i read here (https://stackoverflow.com/a/26893754/11718125) that to fix this i could use plain http.
how could i go about doing this?

The answer you linked to is old, INetC now supports a /WEAKSECURITY switch.
To use plain HTTP, just change the https: part in the URL to http:. This does not work everywhere, some servers might force a redirect to HTTPS.
This works for me:
Section
InitPluginsDir
inetc::get /WEAKSECURITY /SILENT "https://www.gnu.org/licenses/gpl-3.0.txt" "$PluginsDir\License.txt" /END
ClearErrors
FileOpen $1 "$PluginsDir\License.txt" r
IfErrors 0 +2
Abort "No file?"
loop:
FileRead $1 $2
IfErrors +3
DetailPrint $2
Goto loop
FileClose $1
SectionEnd

Related

NSIS AccessControl::GrantOnFile permission failing

I am trying to create and set a directory with NSIS and the accessControl plugin like the following:
CreateDirectory "$APPDATA\${productName}"
; create fileResources directory
CreateDirectory "$APPDATA\${productName}\fileResources"
AccessControl::GrantOnFile "$APPDATA\${productName}\fileResources" "Everyone" "FullAccess"
Pop $0 ; get "Marker" or error msg
StrCmp $0 "Marker" Continue
MessageBox MB_OK|MB_ICONSTOP "Error setting access control for $APPDATA\${productName}\fileResources: $0"
Pop $0 ; pop "Marker"
Continue:
Pop $0
I am receiving the following on $0 what is that response?
I want to make a folder readable and writable by the installed program
I'm guessing that you are building a Unicode installer using NSIS v3 and that you put the wrong plugin in the plugins subdirectory, that is why the result looks chinese.
To install a plugin correctly you need to put the ANSI .dll in NSIS\Plugins\x86-ansi and the Unicode .dll in NSIS\Plugins\x86-unicode.

Load the content of the embedded file into RichEdit control on the custom license page

Requirements / use case:
I have a requirement to implement custom license page in NSIS. The page should look like this: .
On the page I have RichEdit control which has to display the content of a eula.rtf file. This file is available at the compile time and I cannot distribute it separately from the installer, so it has to be somehow embedded into it.
Currently I am using NSIS 2.46 and MUI2. Here is how I create RichEdit control:
nsDialogs::CreateControl /NOUNLOAD "RichEdit20A" ${WS_VISIBLE}|${WS_CHILD}|${WS_TABSTOP}|${WS_VSCROLL}|${ES_MULTILINE}|${ES_WANTRETURN} ${WS_EX_STATICEDGE} 1.32u 56.62u 295.54u 63.38u ""
Pop $hCtl_test_rtLicense
Problem description:
I know that the default MUI2 license page makes use of LicenseData and/or LicenseLangString. As far as I know, in this case the .rtf file is embedded into the installer. Unfortunately I cannot figure out how to load the content from the embedded .rtf file into my RichEdit control, even though I looked through the License.nsh coming with NUI2 and through the NSIS source code as well.
And unfortunately the plugins and scripts I found (LoadRtf plugin, NsRichEdit plugin, this script and one or two more) can only load .rtf file into the RichEdit control at runtime.
Question:
How to load the content from the embedded .rtf file into the RichEdit on the custom page?
If it is not possible, is there any other way to implement my requirement?
The only thing I could think of is wrapping my current installer into another thin NSIS installer which would silently deploy the .rtf file alongside with the current installer. This feels very messy, so I would rather not do that..
The only way to do this is at run-time. To use one of the solutions you linked to you would just extract the .rtf file and call the plugin:
InitPluginsDir ; Initialize $PluginsDir, it is deleted automatically when installer quits
File "/oname=$PluginsDir\lic.rtf" "MyLicense.rtf"
# Call plugin here passing in "$PluginsDir\lic.rtf" as the file to load
Or if you don't want to use 3rd-party plugins:
Page Custom MyPage
Page InstFiles
!include LogicLib.nsh
!include nsDialogs.nsh
!define SF_RTF 2
!define EM_STREAMIN 1097
Function LoadRichRtf
System::Store S
Pop $0 ; hwnd
Pop $1 ; path to rtf
FileOpen $1 $1 r
System::Get "(i, i .R0, i .R1, i .R2)iss"
Pop $2
System::Call "*(*i 0, i 0, k r2)i.r3"
System::Call "USER32::SendMessage(ir0, i${EM_STREAMIN}, i${SF_RTF}, ir3)i.s"
loop:
Pop $0
StrCmp $0 "callback1" 0 done
System::Call 'KERNEL32::ReadFile(ir1, iR0, iR1, iR2, i0)'
Push 0 # callback's return value
System::Call "$2"
Goto loop
done:
System::Free $2
System::Free $3
FileClose $1
System::Store L
FunctionEnd
Var hCtl_test_rtLicense
Function MyPage
nsDialogs::Create 1018
Pop $0
nsDialogs::CreateControl /NOUNLOAD "RichEdit20A" ${WS_VISIBLE}|${WS_CHILD}|${WS_TABSTOP}|${WS_VSCROLL}|${ES_MULTILINE}|${ES_WANTRETURN} ${WS_EX_STATICEDGE} 1.32u 56.62u 295.54u 63.38u ""
Pop $hCtl_test_rtLicense
File "/oname=$PluginsDir\lic.rtf" "c:\some\local\path\License_en_US.rtf"
Push "$PluginsDir\lic.rtf"
Push $hCtl_test_rtLicense
Call LoadRichRtf
nsDialogs::Show
FunctionEnd

NSIS uninstaller privileges according to installer

I have an NSIS installer for an application, which can be run as normal user. But if the user wants to install into the "Program Files" directory, it can still be accomplished by starting the installer with administrator privileges.
Now I have the problem, that the uninstaller is started with user privileges by default, even if the installation took place as administrator. This causes the uninstallation to silently fail. Even worse: It even states that the uninstall process was successful without being able to delete any files.
My question is: Is it possible to create an uninstaller during the installation, which requires (or better: requests itself with) the same privileges as the installation process?
You would have to implement this check yourself. You can check if you are admin in the installer with the UserInfo plugin and then store the result in a .ini, the registry or append the info to the uninstaller.exe:
InstallDir $temp\instdir
Section
UserInfo::GetAccountType
Pop $0
StrCmp $0 "Admin" 0 +2
StrCpy $0 1
IntOp $0 $0 & 1 ; $0 is now 1 if admin or 0 if not
SetOutPath $InstDir
WriteUninstaller "$InstDir\Uninstall.exe"
FileOpen $1 "$InstDir\Uninstall.exe" a
FileSeek $1 0 END
FileWriteByte $1 $0
FileClose $1
SectionEnd
Section Uninstall
FileOpen $1 "$ExePath" r
FileSeek $1 -1 END
FileReadByte $1 $0
FileClose $1
DetailPrint "Installer was admin: $0"
SectionEnd

NSIS AccessControl Plugin disable access to directory for all except Admins and System

I just read bunch of answers about setting permissions to directory by NSIS AccessControl plugin, but all those only show basic usage copy pasted from plugin site... It only shows cases ALL or NOTHING... but how do I disable ALL permissions to directory for everyone except System and Administrators?
AccessControl::DisableFileInheritance "$temp\test.tmp"
Pop $0
DetailPrint $0
AccessControl::ClearOnFile "$temp\test.tmp" "(S-1-5-18)" "FullAccess"
Pop $0
DetailPrint $0
AccessControl::SetOnFile "$temp\test.tmp" "(S-1-5-32-544)" "FullAccess"
Pop $0
DetailPrint $0
This might not be enough, you should probably also use SetFileOwner and maybe SetFileGroup...

Checking if the application is running in NSIS before uninstalling

I am new to NSIS, and I need to know that in the uninstaller, how I can check if the application (which is in C++) is running and close it before uninstalling.
Here is a slightly more friendly version for using NSProcess that requests the app to close rather than terminates it (Owen's answer)
${nsProcess::FindProcess} "${APP_EXE}" $R0
${If} $R0 == 0
DetailPrint "${AppName} is running. Closing it down"
${nsProcess::CloseProcess} "${APP_EXE}" $R0
DetailPrint "Waiting for ${AppName} to close"
Sleep 2000
${Else}
DetailPrint "${APP_EXE} was not found to be running"
${EndIf}
${nsProcess::Unload}
Use the NsProcess plugin. Download it here -> NSProcess
How to use it? As simple as:
${nsProcess::KillProcess} "${APP_EXE}" $R4
where APP_EXE is the name of your application...
The download will also tell you how to use it... :)
Depending on the application, you have a couple of choices:
If your application has a window with a somewhat unique class name, you could use FindWindow
If your application creates a named kernel object (Mutex etc) you can check for it by calling the correct native win32 API with the system plugin
Use a 3rd party plugin like FindProcDLL
Just make sure that the first thing that install or un-install does is to delete all xyz.tmp files in %TEMP (or any other app writable directory) before the below for loop runs. No plugins required.
!macro IsRunning
ExecWait "cmd /c for /f $\"tokens=1,2$\" %i in ('tasklist') do (if /i %i EQU xyz.exe fsutil file createnew $TEMP\xyz.tmp 0)"
IfFileExists $TEMP\xyz.tmp 0 notRunning
;we have atleast one main window active
MessageBox MB_OK|MB_ICONEXCLAMATION "XYZ is running. Please close all instances and retry." /SD IDOK
Abort
notRunning:
!macroEnd

Resources