From 0c34819f2770e273acd34b1c6634e4d2bdaf0ca5 Mon Sep 17 00:00:00 2001 From: George Ostrobrod Date: Sat, 8 Sep 2018 11:37:13 +0300 Subject: [PATCH 1/4] Add support of custom http headers. --- include/winsparkle.h | 19 +++++++++++++++++++ src/dll_api.cpp | 18 ++++++++++++++++++ src/download.cpp | 6 +++--- src/download.h | 2 +- src/settings.cpp | 3 ++- src/settings.h | 22 ++++++++++++++++++++++ src/updatechecker.cpp | 2 +- 7 files changed, 66 insertions(+), 6 deletions(-) diff --git a/include/winsparkle.h b/include/winsparkle.h index 360cdd47..6ed56368 100644 --- a/include/winsparkle.h +++ b/include/winsparkle.h @@ -222,6 +222,25 @@ WIN_SPARKLE_API void __cdecl win_sparkle_set_app_details(const wchar_t *company_ */ WIN_SPARKLE_API void __cdecl win_sparkle_set_app_build_version(const wchar_t *build); +/** + Set custom HTTP header for appcast checks. + + @since 0.7 + + @see win_sparkle_clear_http_headers() +*/ +WIN_SPARKLE_API void __cdecl win_sparkle_add_http_header(const char *name, const char *value); + +/** + Clears all custom HTTP headers previously added using + win_sparkle_set_http_header(). + + @since 0.7 + + @see win_sparkle_add_http_header() +*/ +WIN_SPARKLE_API void __cdecl win_sparkle_clear_http_headers(); + /** Set the registry path where settings will be stored. diff --git a/src/dll_api.cpp b/src/dll_api.cpp index 5ba98768..4bcfba17 100644 --- a/src/dll_api.cpp +++ b/src/dll_api.cpp @@ -174,6 +174,24 @@ WIN_SPARKLE_API void __cdecl win_sparkle_set_app_details(const wchar_t *company_ CATCH_ALL_EXCEPTIONS } +WIN_SPARKLE_API void __cdecl win_sparkle_add_http_header(const char *name, const char *value) +{ + try + { + Settings::AddHttpHeader(name, value); + } + CATCH_ALL_EXCEPTIONS +} + +WIN_SPARKLE_API void __cdecl win_sparkle_clear_http_headers() +{ + try + { + Settings::ClearHttpHeaders(); + } + CATCH_ALL_EXCEPTIONS +} + WIN_SPARKLE_API void __cdecl win_sparkle_set_app_build_version(const wchar_t *build) { try diff --git a/src/download.cpp b/src/download.cpp index b3dac04c..ba38d7c8 100644 --- a/src/download.cpp +++ b/src/download.cpp @@ -188,7 +188,7 @@ void WaitUntilSignaledWithTerminationCheck(Event& event, Thread *thread) public functions *--------------------------------------------------------------------------*/ -void DownloadFile(const std::string& url, IDownloadSink *sink, Thread *onThread, int flags) +void DownloadFile(const std::string& url, IDownloadSink *sink, Thread *onThread, const std::string &headers, int flags) { char url_path[2048]; URL_COMPONENTSA urlc; @@ -234,8 +234,8 @@ void DownloadFile(const std::string& url, IDownloadSink *sink, Thread *onThread, ( inet, url.c_str(), - NULL, // lpszHeaders - -1, // dwHeadersLength + headers.c_str(), + (DWORD)headers.length(), dwFlags, (DWORD_PTR)&context // dwContext ); diff --git a/src/download.h b/src/download.h index e6a2fd7a..815bd5a8 100644 --- a/src/download.h +++ b/src/download.h @@ -92,7 +92,7 @@ enum DownloadFlag @see CheckConnection() */ -void DownloadFile(const std::string& url, IDownloadSink *sink, Thread *onThread, int flags = 0); +void DownloadFile(const std::string& url, IDownloadSink *sink, Thread *onThread, const std::string &headers = "", int flags = 0); } // namespace winsparkle diff --git a/src/settings.cpp b/src/settings.cpp index bcd6c331..b2adb711 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -42,7 +42,8 @@ std::wstring Settings::ms_companyName; std::wstring Settings::ms_appName; std::wstring Settings::ms_appVersion; std::wstring Settings::ms_appBuildVersion; -std::string Settings::ms_DSAPubKey; +std::string Settings::ms_DSAPubKey; +std::string Settings::ms_httpHeaders; /*--------------------------------------------------------------------------* diff --git a/src/settings.h b/src/settings.h index 4dcea637..9e2d9d74 100644 --- a/src/settings.h +++ b/src/settings.h @@ -196,6 +196,27 @@ class Settings ms_appVersion = version; } + /// Add a custom HTT header to requests + static void AddHttpHeader(const char *name, const char *value) + { + CriticalSectionLocker lock(ms_csVars); + ms_httpHeaders += std::string(name) + ": " + value + "\r\n"; + } + + /// Get a string containing all custom HTTP headers + static std::string GetHttpHeaderString() + { + CriticalSectionLocker lock(ms_csVars); + return ms_httpHeaders; + } + + /// Clear previously set HTTP headers + static void ClearHttpHeaders() + { + CriticalSectionLocker lock(ms_csVars); + ms_httpHeaders = ""; + } + /// Set application's build version number static void SetAppBuildVersion(const wchar_t *version) { @@ -323,6 +344,7 @@ class Settings static std::wstring ms_appVersion; static std::wstring ms_appBuildVersion; static std::string ms_DSAPubKey; + static std::string ms_httpHeaders; }; } // namespace winsparkle diff --git a/src/updatechecker.cpp b/src/updatechecker.cpp index 51ef4641..8273a6bb 100644 --- a/src/updatechecker.cpp +++ b/src/updatechecker.cpp @@ -228,7 +228,7 @@ void UpdateChecker::PerformUpdateCheck() CheckForInsecureURL(url, "appcast feed"); StringDownloadSink appcast_xml; - DownloadFile(url, &appcast_xml, this, Download_BypassProxies); + DownloadFile(url, &appcast_xml, this, Settings::GetHttpHeaderString(), Download_BypassProxies); Appcast appcast = Appcast::Load(appcast_xml.data); if (!appcast.ReleaseNotesURL.empty()) From 524ebb6e2bf6b41b5c8e76cc50f5ab3e56759161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Va=CC=81clav=20Slavi=CC=81k?= Date: Sun, 14 Apr 2019 17:12:00 +0200 Subject: [PATCH 2/4] Use std::map<> to implement custom HTTP headers Call the function for customizing HTTP headers win_sparkle_set_http_header(), instead of "add", to express that it doesn't allow duplicates. Use std::map<> for implementation to prevent duplicates. Duplicate HTTP headers are only allowed by the spec in very limited circumstances and cause problems in practice with proxies etc. We intentionally don't want to support that. --- include/winsparkle.h | 4 ++-- src/dll_api.cpp | 4 ++-- src/settings.cpp | 2 +- src/settings.h | 16 ++++++++++------ src/updatechecker.cpp | 2 +- 5 files changed, 16 insertions(+), 12 deletions(-) diff --git a/include/winsparkle.h b/include/winsparkle.h index 6ed56368..9ba63810 100644 --- a/include/winsparkle.h +++ b/include/winsparkle.h @@ -229,7 +229,7 @@ WIN_SPARKLE_API void __cdecl win_sparkle_set_app_build_version(const wchar_t *bu @see win_sparkle_clear_http_headers() */ -WIN_SPARKLE_API void __cdecl win_sparkle_add_http_header(const char *name, const char *value); +WIN_SPARKLE_API void __cdecl win_sparkle_set_http_header(const char *name, const char *value); /** Clears all custom HTTP headers previously added using @@ -237,7 +237,7 @@ WIN_SPARKLE_API void __cdecl win_sparkle_add_http_header(const char *name, const @since 0.7 - @see win_sparkle_add_http_header() + @see win_sparkle_set_http_header() */ WIN_SPARKLE_API void __cdecl win_sparkle_clear_http_headers(); diff --git a/src/dll_api.cpp b/src/dll_api.cpp index 4bcfba17..af15fd7a 100644 --- a/src/dll_api.cpp +++ b/src/dll_api.cpp @@ -174,11 +174,11 @@ WIN_SPARKLE_API void __cdecl win_sparkle_set_app_details(const wchar_t *company_ CATCH_ALL_EXCEPTIONS } -WIN_SPARKLE_API void __cdecl win_sparkle_add_http_header(const char *name, const char *value) +WIN_SPARKLE_API void __cdecl win_sparkle_set_http_header(const char *name, const char *value) { try { - Settings::AddHttpHeader(name, value); + Settings::SetHttpHeader(name, value); } CATCH_ALL_EXCEPTIONS } diff --git a/src/settings.cpp b/src/settings.cpp index b2adb711..7e41f5d0 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -43,7 +43,7 @@ std::wstring Settings::ms_appName; std::wstring Settings::ms_appVersion; std::wstring Settings::ms_appBuildVersion; std::string Settings::ms_DSAPubKey; -std::string Settings::ms_httpHeaders; +std::map Settings::ms_httpHeaders; /*--------------------------------------------------------------------------* diff --git a/src/settings.h b/src/settings.h index 9e2d9d74..67cbe405 100644 --- a/src/settings.h +++ b/src/settings.h @@ -29,6 +29,7 @@ #include "threads.h" #include "utils.h" +#include #include #include @@ -197,24 +198,27 @@ class Settings } /// Add a custom HTT header to requests - static void AddHttpHeader(const char *name, const char *value) + static void SetHttpHeader(const char *name, const char *value) { CriticalSectionLocker lock(ms_csVars); - ms_httpHeaders += std::string(name) + ": " + value + "\r\n"; + ms_httpHeaders[name] = value; } /// Get a string containing all custom HTTP headers - static std::string GetHttpHeaderString() + static std::string GetHttpHeadersString() { CriticalSectionLocker lock(ms_csVars); - return ms_httpHeaders; + std::string out; + for (auto i = ms_httpHeaders.begin(); i != ms_httpHeaders.end(); ++i) + out += i->first + ": " + i->second + "\r\n"; + return out; } /// Clear previously set HTTP headers static void ClearHttpHeaders() { CriticalSectionLocker lock(ms_csVars); - ms_httpHeaders = ""; + ms_httpHeaders.clear(); } /// Set application's build version number @@ -344,7 +348,7 @@ class Settings static std::wstring ms_appVersion; static std::wstring ms_appBuildVersion; static std::string ms_DSAPubKey; - static std::string ms_httpHeaders; + static std::map ms_httpHeaders; }; } // namespace winsparkle diff --git a/src/updatechecker.cpp b/src/updatechecker.cpp index 8273a6bb..a25d157d 100644 --- a/src/updatechecker.cpp +++ b/src/updatechecker.cpp @@ -228,7 +228,7 @@ void UpdateChecker::PerformUpdateCheck() CheckForInsecureURL(url, "appcast feed"); StringDownloadSink appcast_xml; - DownloadFile(url, &appcast_xml, this, Settings::GetHttpHeaderString(), Download_BypassProxies); + DownloadFile(url, &appcast_xml, this, Settings::GetHttpHeadersString(), Download_BypassProxies); Appcast appcast = Appcast::Load(appcast_xml.data); if (!appcast.ReleaseNotesURL.empty()) From e50d9f4f68607f677e3e85e3d58b4d587cb9a6d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Va=CC=81clav=20Slavi=CC=81k?= Date: Sun, 14 Apr 2019 17:09:52 +0200 Subject: [PATCH 3/4] Add example of HTTP headers customization Show how to modify HTTP headers and explain where and what can be further customized in the example. --- examples/psdk/app_psdk.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/examples/psdk/app_psdk.c b/examples/psdk/app_psdk.c index d3317221..a368e5cf 100644 --- a/examples/psdk/app_psdk.c +++ b/examples/psdk/app_psdk.c @@ -168,6 +168,16 @@ int APIENTRY WinMain(HINSTANCE hInstance, ShowWindow(g_hwndMain, nCmdShow); + /* + Configure WinSparkle using win_sparkle_set_* functions *before* + calling win_sparkle_init(). This is optional and the following example + of doing that is just that, an example. + + See e.g. https://github.com/vslavik/poedit/blob/master/src/edapp.cpp + for another, real-life example of use. + */ + win_sparkle_set_http_header("X-Product-License", "Pro"); + /* Initialize WinSparkle as soon as the app itself is initialized, right before entering the event loop. This also checks for updates and shows update UI if there any. */ From cc790f0db5d8d0a3c3ee07e9586bde510ab5f4ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Va=CC=81clav=20Slavi=CC=81k?= Date: Sun, 14 Apr 2019 17:17:52 +0200 Subject: [PATCH 4/4] Increase version to 0.7.0 API changes warrant it. --- include/winsparkle-version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/winsparkle-version.h b/include/winsparkle-version.h index 60fc2929..b14f59ea 100644 --- a/include/winsparkle-version.h +++ b/include/winsparkle-version.h @@ -31,7 +31,7 @@ *--------------------------------------------------------------------------*/ #define WIN_SPARKLE_VERSION_MAJOR 0 -#define WIN_SPARKLE_VERSION_MINOR 6 +#define WIN_SPARKLE_VERSION_MINOR 7 #define WIN_SPARKLE_VERSION_MICRO 0 /**