File: update.cpp

package info (click to toggle)
nsis 3.11-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 12,496 kB
  • sloc: cpp: 39,326; ansic: 27,284; python: 1,386; asm: 712; xml: 409; pascal: 231; makefile: 225; javascript: 67
file content (148 lines) | stat: -rwxr-xr-x 4,876 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// Unicode support by Jim Park -- 08/20/2007

#include "makensisw.h"
#include "update.h"
#include <wininet.h>
#include "utils.h" // OpenUrlInDefaultBrowser

#define mbtitle "NSIS Update"

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 = LoadSysLibrary("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 = LoadSysLibrary("WinHTTP");
  if (hMod && FormatMessageA(flags|FORMAT_MESSAGE_FROM_HMODULE, hMod, ec, 0, (LPSTR) &buf, 0, 0))
    return buf;
#endif
  return NULL;
}

static void InetWorkOnline(HINTERNET hInet)
{
  //msdn.microsoft.com/en-us/library/Aa768170#Supporting Offline Browsing in Applications and Components
  DWORD cbio = sizeof(DWORD), op32;
  if (InternetQueryOption(hInet, INTERNET_OPTION_CONNECTED_STATE, &op32, &cbio))
  {
    if (INTERNET_STATE_DISCONNECTED_BY_USER & op32)
    {
      INTERNET_CONNECTED_INFO ci = { INTERNET_STATE_CONNECTED, 0 };
      InternetSetOption(hInet, INTERNET_OPTION_CONNECTED_STATE, &ci, sizeof(ci));
    }
  }
}

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;
}

static DWORD CALLBACK UpdateCheckWebrequestThread(LPVOID ThreadParam)
{
  char buf[300];
  wsprintfA(buf, "%s%s", NSIS_UC_URL, g_sdata.brandingv);

  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+1];
      DWORD cbRecv;
      gle = InetSynchronousReadFile(hConn, response, sizeof(response)-1, &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);
    }
    InternetCloseHandle(hInet);
  }

  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);
    }

    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);
  }
  return 0;
}

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.", mbtitle, MB_OK|MB_ICONSTOP);
    return;
  }

  EnableMenuItem(g_sdata.menu, IDM_NSISUPDATE, MF_GRAYED);
  DWORD tid;
  CloseHandle(CreateThread(NULL, 0, UpdateCheckWebrequestThread, (LPVOID) g_sdata.hwnd, 0, &tid));
}