MakeNSISW now uses WinInet when checking for updates

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6604 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
anders_k 2015-09-07 21:31:50 +00:00
parent e58680c996
commit 873e860f57
20 changed files with 144 additions and 1650 deletions

View file

@ -2,136 +2,146 @@
#include "makensisw.h"
#include "update.h"
#include "utils.h" // OpenUrlInDefaultBrowser
#include "jnetlib/httpget.h"
#define mbtitle "NSIS Update"
static BOOL update_initialized = FALSE;
static JNL_AsyncDNS *g_dns = NULL;
void InitializeUpdate() {
if (update_initialized)
return;
update_initialized = TRUE;
JNL::open_socketlib();
g_dns = new JNL_AsyncDNS();
static LPSTR InetGetErrorStringAllocA(DWORD ec)
{
LPSTR buf;
DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_IGNORE_INSERTS;
if (FormatMessageA(flags|FORMAT_MESSAGE_FROM_SYSTEM, 0, ec, 0, (LPSTR) &buf, 0, 0))
return buf;
HMODULE hMod = GetModuleHandle(TEXT("WinInet"));
if (hMod && FormatMessageA(flags|FORMAT_MESSAGE_FROM_HMODULE, hMod, ec, 0, (LPSTR) &buf, 0, 0))
return buf;
#if 0 // We are not using WinHttp* functions
hMod = GetModuleHandle(TEXT("WinHTTP"));
if (hMod && FormatMessageA(flags|FORMAT_MESSAGE_FROM_HMODULE, hMod, ec, 0, (LPSTR) &buf, 0, 0))
return buf;
#endif
return NULL;
}
void FinalizeUpdate() {
if (!update_initialized)
return;
delete g_dns;
JNL::close_socketlib();
}
int getProxyInfo(char *out) {
DWORD v=0;
HKEY hKey;
if (RegOpenKeyExA(HKEY_CURRENT_USER,"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",0,KEY_READ,&hKey) == ERROR_SUCCESS) {
DWORD l = 4;
DWORD t;
if (RegQueryValueExA(hKey,"ProxyEnable",NULL,&t,(unsigned char *)&v,&l) == ERROR_SUCCESS && t == REG_DWORD) {
l=8192;
if (RegQueryValueExA(hKey,"ProxyServer",NULL,&t,(unsigned char *)out,&l ) != ERROR_SUCCESS || t != REG_SZ) {
v=0;
*out=0;
}
}
else v=0;
out[8192-1]=0;
RegCloseKey(hKey);
}
return v;
}
DWORD CALLBACK UpdateThread(LPVOID v) {
#define RSZ 30
int len;
char response[RSZ], *r;
char url[300];
BOOL error = FALSE;
static char pbuf[8192];
char *p=NULL;
*response = 0;
if (getProxyInfo(pbuf))
static void InetWorkOnline(HINTERNET hInet)
{
//msdn.microsoft.com/library/default.asp?url=/workshop/components/offline/offline.asp#Supporting Offline Browsing in Applications and Components
DWORD cbio = sizeof(DWORD), op32;
if (InternetQueryOption(hInet, INTERNET_OPTION_CONNECTED_STATE, &op32, &cbio))
{
p=strstr(pbuf,"http=");
if (!p) p=pbuf;
else {
p+=5;
if (INTERNET_STATE_DISCONNECTED_BY_USER & op32)
{
INTERNET_CONNECTED_INFO ci = { INTERNET_STATE_CONNECTED, 0 };
InternetSetOption(hInet, INTERNET_OPTION_CONNECTED_STATE, &ci, sizeof(ci));
}
char *tp=strstr(p,";");
if (tp) *tp=0;
char *p2=strstr(p,"=");
if (p2) p=0; // we found the wrong proxy
}
}
InitializeUpdate();
static DWORD InetSynchronousReadFile(HINTERNET hConn, void*Buffer, DWORD cbBuffer, DWORD*pcbReceived)
{
*pcbReceived = 0;
for (DWORD cbio;;)
{
if (!cbBuffer)
break;
if (!InternetReadFile(hConn, Buffer, cbBuffer, &cbio))
return GetLastError();
if (!cbio)
break; // EOF, we are done.
Buffer = ((char*)Buffer) + cbio, cbBuffer -= cbio;
(*pcbReceived) += cbio;
}
return ERROR_SUCCESS;
}
JNL_HTTPGet *get = new JNL_HTTPGet(g_dns,8192,(p&&p[0])?p:NULL);
lstrcpyA(url,NSIS_UPDATE);
lstrcatA(url,g_sdata.brandingv);
static DWORD CALLBACK UpdateCheckWebrequestThread(LPVOID ThreadParam)
{
char buf[300];
wsprintfA(buf, "%s%s", NSIS_UC_URL, g_sdata.brandingv);
lstrcpyA(response,"");
get->addheader("User-Agent: MakeNSISw (jnetlib)");
get->addheader("Accept:*/*");
get->connect(url);
while (1) {
int st=get->run();
if (st<0) { error = TRUE; break; }//error
if (get->get_status()==2) {
while( (len=get->bytes_available()) ) {
char b[RSZ];
if (len>RSZ) len=RSZ;
if (lstrlenA(response)+len>RSZ) break;
len=get->get_bytes(b,len);
b[len]=0;
lstrcatA(response,b);
InternetAttemptConnect(0);
UINT mbicon = MB_ICONINFORMATION;
LPCSTR msg = NULL;
HINTERNET hInet = InternetOpenA("MakeNSISw (WinInet)", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
DWORD gle = GetLastError();
if (hInet)
{
InetWorkOnline(hInet);
// Note: InternetOpenUrlW does not handle the http headers in the same way, be careful if you stop forcing the A version
static const CHAR httpheaders[] = "Accept:*/*\r\n";
DWORD connflags = INTERNET_FLAG_NO_UI|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS;
connflags |= INTERNET_FLAG_NO_CACHE_WRITE|INTERNET_FLAG_NO_COOKIES;
connflags |= INTERNET_FLAG_PRAGMA_NOCACHE|INTERNET_FLAG_RELOAD;
//if ((32|buf[4]) == 's') connflags |= INTERNET_FLAG_SECURE;
HINTERNET hConn = InternetOpenUrlA(hInet, buf, httpheaders, -1, connflags, 0);
gle = GetLastError();
if (hConn)
{
char response[30];
DWORD cbRecv;
gle = InetSynchronousReadFile(hConn, response, sizeof(response), &cbRecv);
if (!gle)
{
response[cbRecv] = '\0';
switch(response[0])
{
case '0':
msg = "There is no update available for NSIS at this time.";
break;
case '1':
case '2':
if (cbRecv > 2 && '|' == response[1])
{
const char *reltypestr = '1' == response[0] ? "it" : "this preview release";
wsprintfA(buf, "NSIS %.50s is now available. Would you like to download %s now?", response+2, reltypestr);
mbicon = MB_ICONQUESTION, msg = buf;
break;
}
// fall through
default:
gle = ERROR_INVALID_DATA;
}
}
InternetCloseHandle(hConn);
}
if (st==1) break; //closed
InternetCloseHandle(hInet);
}
r = response;
while (r&&*r) {
if (*r=='\n') { *r = 0; break; }
r++;
}
if (error) {
char buf[1000];
wsprintfA(buf, "There was a problem checking for an update. Please try again later.\n\nError: %s",get->geterrorstr());
MessageBoxA(g_sdata.hwnd,buf,"NSIS Update",MB_OK|MB_ICONINFORMATION);
}
else if (*response=='1'&&lstrlenA(response)>2) {
char buf[200];
wsprintfA(buf, "NSIS %s is now available. Would you like to download it now?",response+2);
if (MessageBoxA(g_sdata.hwnd,buf,"NSIS Update",MB_YESNO|MB_ICONINFORMATION)==IDYES) {
ShellExecuteA(g_sdata.hwnd,"open",NSIS_DL_URL,NULL,NULL,SW_SHOWNORMAL);
HWND hwndOwner = (HWND) ThreadParam;
// Hopefully we don't end up with a race where our main window has been closed
// and the HWND has been reused just as this thread completes its work
if (IsWindow(hwndOwner))
{
if (!msg)
{
LPSTR dynbuf = InetGetErrorStringAllocA(gle);
wsprintfA(buf, "There was a problem checking for updates, please try again later.\n\nError: %u %.200s", gle, dynbuf ? dynbuf : "");
mbicon = MB_ICONSTOP, msg = buf;
LocalFree(dynbuf);
}
}
else if (*response=='2'&&lstrlenA(response)>2) {
char buf[200];
wsprintfA(buf,"NSIS %s is now available. Would you like to download this preview release now?",response+2);
if (MessageBoxA(g_sdata.hwnd,buf,"NSIS Update",MB_YESNO|MB_ICONINFORMATION)==IDYES) {
ShellExecuteA(g_sdata.hwnd,"open",NSIS_DL_URL,NULL,NULL,SW_SHOWNORMAL);
UINT mbtype = MB_ICONQUESTION == mbicon ? MB_YESNO : MB_OK;
int mbret = MessageBoxA(hwndOwner, msg, mbtitle, mbtype|mbicon);
if (mbret == IDYES && mbtype == MB_YESNO)
{
OpenUrlInDefaultBrowser(hwndOwner, NSIS_DL_URL);
}
EnableMenuItem(g_sdata.menu, IDM_NSISUPDATE, MF_ENABLED);
}
else MessageBoxA(g_sdata.hwnd,"There is no update available for NSIS at this time.","NSIS Update",MB_OK|MB_ICONINFORMATION);
delete get;
EnableMenuItem(g_sdata.menu,IDM_NSISUPDATE,MF_ENABLED);
return 0;
}
void Update() {
if (strstr(g_sdata.brandingv,"cvs"))
void CheckForUpdate()
{
if (strstr(g_sdata.brandingv, "cvs"))
{
MessageBoxA(g_sdata.hwnd,"Cannot check for new version of nightly builds. To update, download a new nightly build.","NSIS Update",MB_OK|MB_ICONSTOP);
MessageBoxA(g_sdata.hwnd, "Cannot check for new version of nightly builds. To update, download a new nightly build.", mbtitle, MB_OK|MB_ICONSTOP);
return;
}
EnableMenuItem(g_sdata.menu,IDM_NSISUPDATE,MF_GRAYED);
EnableMenuItem(g_sdata.menu, IDM_NSISUPDATE, MF_GRAYED);
DWORD tid;
CloseHandle(CreateThread(NULL,0,UpdateThread,NULL,0,&tid));
CloseHandle(CreateThread(NULL, 0, UpdateCheckWebrequestThread, (LPVOID) g_sdata.hwnd, 0, &tid));
}