Switch to libcurl for update check

Removes dependence on undermaintained luasocket and luasec libraries.

As an additional benefit, update checks can now be disabled at build
time for distros that would prefer not to show it.
This commit is contained in:
Stephen E. Baker
2024-04-20 23:41:48 -04:00
parent a71ee098ea
commit b9b831ce12
13 changed files with 161 additions and 125 deletions

View File

@@ -50,7 +50,8 @@ jobs:
- name: Install CorsixTH requirements
run: |
sudo apt-get install libsdl2-dev libsdl2-mixer-dev \
libavcodec-dev libavformat-dev libavutil-dev libswresample-dev libswscale-dev
libavcodec-dev libavformat-dev libavutil-dev libswresample-dev \
libswscale-dev libcurl4-openssl-dev
- name: Install static analysis requirements
if: matrix.static_analysis
run: |
@@ -68,11 +69,11 @@ jobs:
sudo luarocks --lua-version 5.4 install luafilesystem
- name: Install CMake 3.10
- name: Install CMake 3.14
if: matrix.cmake
run: |
# Install CMake version 3.10, the oldest CorsixTH-supported version, which does not support Lua 5.4
curl -L https://github.com/Kitware/CMake/releases/download/v3.10.3/cmake-3.10.3-Linux-x86_64.sh -o cmake.sh
# Install CMake version 3.14, the oldest CorsixTH-supported version, which does not support Lua 5.4
curl -L https://github.com/Kitware/CMake/releases/download/v3.14.6/cmake-3.14.6-Linux-x86_64.sh -o cmake.sh
sudo bash cmake.sh --prefix=/usr/local/ --exclude-subdir --skip-license
cmake --version
- name: Create CorsixTH${{ matrix.animview }} makefiles with ${{ matrix.lua }}

View File

@@ -1,55 +1,8 @@
# Add an extra step to copy LUA files from vcpkg
add_custom_command(TARGET CorsixTH POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/share/lua/socket"
$<TARGET_FILE_DIR:CorsixTH>/socket
)
add_custom_command(TARGET CorsixTH POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/share/lua/ssl"
$<TARGET_FILE_DIR:CorsixTH>/ssl
)
add_custom_command(TARGET CorsixTH POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
"${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/share/lua/ltn12.lua"
"${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/share/lua/mime.lua"
"${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/share/lua/re.lua"
"${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/share/lua/socket.lua"
"${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/share/lua/ssl.lua"
"${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/$<$<CONFIG:Debug>:debug/>bin/lfs.dll"
"${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/$<$<CONFIG:Debug>:debug/>bin/lpeg.dll"
$<TARGET_FILE_DIR:CorsixTH>
)
add_custom_command(TARGET CorsixTH POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
"${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/$<$<CONFIG:Debug>:debug/>bin/lua-ssl.dll"
$<TARGET_FILE_DIR:CorsixTH>/ssl.dll
)
if(${VCPKG_TARGET_TRIPLET} MATCHES "x64-windows.*")
set(_OPENSSL_SUFFIX "-x64")
else()
set(_OPENSSL_SUFFIX "")
endif()
add_custom_command(TARGET CorsixTH POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
"${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/$<$<CONFIG:Debug>:debug/>bin/libcrypto-3${_OPENSSL_SUFFIX}.dll"
"${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/$<$<CONFIG:Debug>:debug/>bin/libssl-3${_OPENSSL_SUFFIX}.dll"
$<TARGET_FILE_DIR:CorsixTH>
)
add_custom_command(TARGET CorsixTH POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
"${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/$<$<CONFIG:Debug>:debug/>bin/mime/core.dll"
$<TARGET_FILE_DIR:CorsixTH>/mime/core.dll
)
add_custom_command(TARGET CorsixTH POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
"${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/$<$<CONFIG:Debug>:debug/>bin/socket/core.dll"
$<TARGET_FILE_DIR:CorsixTH>/socket/core.dll
)

View File

@@ -18,7 +18,7 @@
# - BUILD_ANIMVIEW : Generate AnimView build files (no)
# - BUILD_TOOLS : Generate cli tools
cmake_minimum_required(VERSION 3.10)
cmake_minimum_required(VERSION 3.14)
# Define our options
option(BUILD_CORSIXTH "Builds the main game" ON)
@@ -26,6 +26,7 @@ option(WITH_AUDIO "Activate sound" ON)
option(WITH_FREETYPE2 "Enhanced font support" ON)
option(WITH_MOVIES "Activate in game movies" ON)
option(WITH_LUAJIT "Use LuaJIT instead of Lua" OFF)
option(WITH_UPDATE_CHECK "Check for new versions" ON)
option(USE_SOURCE_DATADIRS "Use the source directory for loading resources. Incompatible with the install target" OFF)
option(ENABLE_UNIT_TESTS "Enables Unit Testing Targets" OFF)
option(BUILD_ANIMVIEW "Build the animation viewer as part of the build process" OFF)
@@ -39,6 +40,9 @@ endif()
if(BUILD_ANIMVIEW)
list(APPEND VCPKG_MANIFEST_FEATURES "animview")
endif()
if(WITH_UPDATE_CHECK)
list(APPEND VCPKG_MANIFEST_FEATURES "updatecheck")
endif()
project(CorsixTH_Top_Level)
@@ -72,7 +76,6 @@ if(APPLE)
option(WITH_LUAROCKS "Install required luarocks in the app" OFF)
endif()
if(WITH_AUDIO)
set(CORSIX_TH_USE_SDL_MIXER ON)
message("Note: SDL audio is enabled (default)")
@@ -102,6 +105,12 @@ else()
message("Note: FreeType2 is disabled")
endif()
if(WITH_UPDATE_CHECK)
message("Note: Update check is enabled (default)")
else()
message("Note: Update check is disabled")
endif()
if(MSVC)
if(WITH_VLD)
set(CORSIX_TH_USE_VLD ON)

View File

@@ -10,7 +10,8 @@
"ENABLE_UNIT_TESTS": "ON",
"BUILD_ANIMVIEW": "ON",
"BUILD_TOOLS": "ON",
"CMAKE_BUILD_TYPE": "Debug"
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
"CMAKE_BUILD_TYPE": "Debug"
}
},
{

View File

@@ -215,6 +215,16 @@ if(CORSIX_TH_USE_FREETYPE2)
endif()
endif()
if(WITH_UPDATE_CHECK)
find_package(CURL REQUIRED COMPONENTS HTTPS SSL)
if(CURL_FOUND)
target_link_libraries(CorsixTH CURL::libcurl)
message(" Curl found")
else()
message(FATAL_ERROR "Error: curl not found")
endif()
endif()
if(MSVC AND CORSIX_TH_USE_VLD)
find_package(VLD REQUIRED)
if(VLD_FOUND)

View File

@@ -32,4 +32,4 @@ Note: This file compiles as both Lua and C++. */
#endif /*]] --*/
return 2686;
return 2687;

View File

@@ -1629,6 +1629,7 @@ end
-- a specific savegame version is from.
function App:getVersion(version)
local ver = version or self.savegame_version
if ver > 180 then
return "Trunk"
elseif ver > 170 then
@@ -1832,34 +1833,19 @@ function App:checkForUpdates()
-- Default language to use for the changelog if no localised version is available
local default_language = "en"
local update_url = 'https://corsixth.com/CorsixTH/check-for-updates'
local current_version = self:getVersion()
-- Only URLs that match this list of trusted domains will be accepted.
local trusted_domains = { 'corsixth.com', 'github.com', 'corsixth.github.io' }
-- Only check for updates against released versions
if current_version == "Trunk" then
print("Will not check for updates since this is the Trunk version.")
return
end
local luasocket, _ = pcall(require, "socket")
local luasec, _ = pcall(require, "ssl.https")
if not (luasocket and luasec) then
print("Cannot check for updates since LuaSocket and/or LuaSec are not available.")
return
end
local http = require("socket.http")
local url = require("socket.url")
http.TIMEOUT = 2
print("Checking for CorsixTH updates...")
local update_body, status, _ = http.request(update_url)
local update_body, err = TH.FetchLatestVersionInfo()
if not update_body or (status ~= 200) then
print("Couldn't check for updates. Server returned code: " .. status)
print("Check that you have an active internet connection and that CorsixTH is allowed in your firewall.")
if not update_body then
print("Couldn't check for updates: " .. err)
return
end
@@ -1872,6 +1858,7 @@ function App:checkForUpdates()
local function compare_versions()
local current_major, current_minor, current_revision = string.match(current_version, "(%d+)%.(%d+)%.?(%d*)")
current_major, current_minor = tonumber(current_major), tonumber(current_minor)
if current_major > update_table.major then return true
elseif current_major < update_table.major then return false
end
@@ -1889,16 +1876,18 @@ function App:checkForUpdates()
end
-- Check to make sure download URL is trusted
local download_url = url.parse(update_table.download_url)
local valid_url = false
for _, v in ipairs(trusted_domains) do
if download_url.host == v then
valid_url = true
local download_url = update_table.download_url
local trusted_url = false
local trusted_prefixes = { 'https://corsixth.com/', 'https://github.com/', 'https://corsixth.github.io/' }
for _, v in ipairs(trusted_prefixes) do
if download_url:sub(1, #v) == v then
trusted_url = true
break
end
end
if not valid_url then
print("Update download url is not on the trusted domains list (" .. update_table.download_url .. ")")
if not trusted_url then
print("Update download url is not on the trusted domains list (" .. download_url .. ")")
return
end
@@ -1913,7 +1902,7 @@ function App:checkForUpdates()
print("New version found: " .. new_version)
-- Display the update window
self.ui:addWindow(UIUpdate(self.ui, current_version, new_version, changelog, update_table.download_url))
self.ui:addWindow(UIUpdate(self.ui, current_version, new_version, changelog, download_url))
end
-- Free up / stop any resources relying on the current video object

View File

@@ -60,6 +60,11 @@ SOFTWARE.
// Chinese are desired.
#cmakedefine CORSIX_TH_USE_FREETYPE2
/** Update check options **/
// If defined then an http request will be made using libcurl to check to see
// if the current version is the latest.
#cmakedefine WITH_UPDATE_CHECK
#ifdef _MSC_VER
#define CORSIX_TH_USE_PACK_PRAGMAS 1
#define CORSIX_TH_PACKED_FLAGS

View File

@@ -20,14 +20,24 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "config.h"
#include <cstdio>
#include <cstring>
#include <stdexcept>
#include <string>
#ifdef WITH_UPDATE_CHECK
#include <curl/curl.h>
#endif
#include "bootstrap.h"
#include "th.h"
#include "th_lua_internal.h"
const char* update_check_url =
"https://corsixth.com/CorsixTH/check-for-updates";
void lua_register_anims(const lua_register_state* pState);
void lua_register_gfx(const lua_register_state* pState);
void lua_register_map(const lua_register_state* pState);
@@ -154,6 +164,55 @@ const uint8_t* luaT_checkfile(lua_State* L, int idx, size_t* pDataLen) {
namespace {
#ifdef WITH_UPDATE_CHECK
// https://everything.curl.dev/transfers/callbacks/write.html
size_t version_info_write_callback(char* ptr, size_t size, size_t nmemb,
void* userdata) {
size_t realsize = size * nmemb;
std::string* resp = static_cast<std::string*>(userdata);
resp->append(ptr, realsize);
return realsize;
}
#endif
int l_fetch_latest_version_info(lua_State* L) {
#ifdef WITH_UPDATE_CHECK
CURL* curl = curl_easy_init();
if (curl == nullptr) {
lua_pushnil(L);
lua_pushliteral(L, "Could not initialize curl");
return 2;
}
curl_easy_setopt(curl, CURLOPT_URL, update_check_url);
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L);
curl_easy_setopt(curl, CURLOPT_MAXFILESIZE, 4096L);
std::string response;
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, version_info_write_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&response);
CURLcode res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
if (res != CURLE_OK) {
lua_pushnil(L);
lua_pushstring(L, curl_easy_strerror(res));
return 2;
}
lua_pushstring(L, response.c_str());
lua_pushnil(L);
return 2;
#else
lua_pushnil(L);
lua_pushliteral(L, "Update check was not enabled at compile time.");
return 2;
#endif
}
int l_load_strings(lua_State* L) {
size_t iDataLength;
const uint8_t* pData = luaT_checkfile(L, 1, &iDataLength);
@@ -244,6 +303,8 @@ int luaopen_th(lua_State* L) {
add_lua_function(pState, l_load_strings, "LoadStrings");
add_lua_function(pState, l_get_compile_options, "GetCompileOptions");
add_lua_function(pState, bootstrap_lua_resources, "GetBuiltinFont");
add_lua_function(pState, l_fetch_latest_version_info,
"FetchLatestVersionInfo");
// Classes
lua_register_map(pState);

View File

@@ -33,6 +33,10 @@ SOFTWARE.
#ifdef CORSIX_TH_USE_SDL_MIXER
#include <SDL_mixer.h>
#endif
#ifdef WITH_UPDATE_CHECK
#include <curl/curl.h>
#endif
// Template magic for checking type equality
template <typename T1, typename T2>
struct types_equal {
@@ -75,6 +79,10 @@ int main(int argc, char** argv) {
int number_is_double[types_equal<lua_Number, double>::result];
};
#ifdef WITH_UPDATE_CHECK
curl_global_init(CURL_GLOBAL_DEFAULT);
#endif
bool bRun = true;
while (bRun) {
@@ -124,5 +132,8 @@ int main(int argc, char** argv) {
std::printf("\n\nRestarting...\n\n\n");
}
}
#ifdef WITH_UPDATE_CHECK
curl_global_cleanup();
#endif
return 0;
}

View File

@@ -166,31 +166,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-------------------------------------------------------------------------------
Uses the luasocket library available from
https://lunarmodules.github.io/luasocket/ under the following terms:
Copyright (C) 2004-2022 Diego Nehab
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
-------------------------------------------------------------------------------
Uses the whereami library, which is available from
https://github.com/gpakosz/whereami under the following terms:
@@ -214,6 +189,34 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-------------------------------------------------------------------------------
Uses the libcurl library, which is available from
https://curl.se/ under the following terms:
COPYRIGHT AND PERMISSION NOTICE
Copyright (c) 1996 - 2024, Daniel Stenberg, daniel@haxx.se, and many
contributors, see the THANKS file.
All rights reserved.
Permission to use, copy, modify, and distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice
and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of a copyright holder shall not be
used in advertising or otherwise to promote the sale, use or other dealings in
this Software without prior written authorization of the copyright holder.
-------------------------------------------------------------------------------
Uses the Mersenne twister random number generator, which is available from
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html under the following
terms:

View File

@@ -26,12 +26,6 @@ dir="$($luarocks show --rock-tree luafilesystem)"
#always_copy=true
# Always build new rocks if uncommented
#always_build=true
# Do not install luasocket and luasec if uncommented
#skip_luasocket=true
if [ "$skip_luasocket" != "true" ]; then
# Path to the folder containing openssl, for luasec
openssl_path=$( (which openssl | brew --prefix) | sed 's/\bin\/openssl//')
fi
set -ae
if [ "$CTH_VERBOSE" ] || [ "$CI" ]; then
@@ -78,21 +72,10 @@ else
luarocks="$luarocks install --lua-version $lua --tree ."
$luarocks luafilesystem
$luarocks lpeg
if [ -z "$skip_luasocket" ]; then
$luarocks luasocket
$luarocks luasec OPENSSL_DIR="$openssl_path"
fi
echo "Installed local luarocks for $lua."
fi
# Move into place for CorsixTH
rsync -r "lib/lua/$lua/"lpeg.so "lib/lua/$lua/"lfs.so .
rsync -r "share/lua/$lua/"re.lua ./Lua/
if [ -z "$skip_luasocket" ]; then
rsync -r "lib/lua/$lua/"ssl.so "lib/lua/$lua/"mime . 2>/dev/null
rsync -r "lib/lua/$lua/socket/core.so" socket/ 2>/dev/null
rsync -r "share/lua/$lua/"ltn12.lua "share/lua/$lua/"mime.lua "share/lua/$lua/"socket.lua "share/lua/$lua/"ssl \
"share/lua/$lua/"ssl.lua ./Lua/ 2>/dev/null
rsync -r "share/lua/$lua/"socket/*.lua ./Lua/socket 2>/dev/null
fi
rm -rf lib/ share/

View File

@@ -26,8 +26,6 @@
"opusfile"
]
},
"luasocket",
"luasec",
"catch2"
],
"features": {
@@ -37,6 +35,18 @@
"wxwidgets"
]
},
"updatecheck": {
"description": "Support checking for game updates",
"dependencies": [
{
"name": "curl",
"default-features": false,
"features": [
"ssl"
]
}
]
},
"movies": {
"description": "In game video support",
"dependencies": [