Skip to content

Commit

Permalink
[TEST] Make update checker use libcurl and https
Browse files Browse the repository at this point in the history
That horrible hack with the curl_meson subproject is needed since the
libcurl dependency generated by libcurl's cmake build system (via
meson's cmake module) includes its internal files its
include_directories, which shadows certain other includes. So instead
we manually replace the include_directories with the correct ones, taken
from a separate meson subproject. This needs an additional wrap file,
but it points to the same subproject directory in order to prevent there
being multiple downloads of the same libcurl source that could go out of
sync at some point.

Co-authored-by: sepro <[email protected]>
  • Loading branch information
arch1t3cht and seproDev committed Nov 1, 2023
1 parent f02c38b commit 2f56d11
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 42 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ subprojects/avisynth
subprojects/bestsource/
subprojects/boost*/
subprojects/cairo*
subprojects/curl-*
subprojects/dav1d
subprojects/ffmpeg
subprojects/ffms2
Expand Down
37 changes: 37 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ if get_option('build_appimage')
conf.set('APPIMAGE_BUILD', 1)
endif
conf.set('WITH_UPDATE_CHECKER', get_option('enable_update_checker'))
conf.set_quoted('UPDATE_CHECKER_SERVER', get_option('update_server'))
conf.set_quoted('UPDATE_CHECKER_BASE_URL', get_option('update_url'))

deps = []
deps_inc = []
Expand Down Expand Up @@ -348,6 +350,41 @@ endif
conf_platform = configuration_data()
conf_platform.set('DEFAULT_PLAYER_AUDIO', def_audio)

if get_option('enable_update_checker')
libcurl_dep = dependency('libcurl', required: false)

if (not libcurl_dep.found())
libcurl_opt = cmake.subproject_options()
options_dict = {
'HTTP_ONLY': true,
'BUILD_CURL_EXE': false,
'CMAKE_BUILD_TYPE': get_option('buildtype') == 'release' ? 'Release' : 'Debug',
}
if host_machine.system() == 'windows'
options_dict += {'CURL_USE_SCHANNEL': true}
deps += cc.find_library('crypt32')
elif host_machine.system() == 'darwin'
options_dict += {'CURL_USE_SECTRANSP': true}
else
options_dict += {'CURL_USE_OPENSSL': true}
endif
if get_option('default_library') == 'static' and (host_machine.system() == 'windows' or host_machine.system() == 'darwin')
options_dict += {'BUILD_SHARED_LIBS': false}
add_project_arguments('-DCURL_STATICLIB', language: ['cpp'])
endif
libcurl_opt.add_cmake_defines(options_dict)
libcurl = cmake.subproject('curl', options: libcurl_opt)

libcurl_dep = libcurl.dependency('libcurl')

# I hate this I hate this I hate this I hate this I hate this I hate this I hate this I hate this I hate this I hate this
libcurl_dep = libcurl_dep.partial_dependency(compile_args: true, link_args: true, links: true, sources: true)
libcurl_fixed_inc = declare_dependency(include_directories: subproject('curl_meson').get_variable('libcurl_fixed_inc'))
deps += [libcurl_fixed_inc]
endif
deps += [libcurl_dep]
endif

luajit = dependency('luajit', version: '>=2.0.0', required: get_option('system_luajit'))
if luajit.found() and luajit.type_name() != 'internal'
luajit_test = cc.run('''#include <lauxlib.h>
Expand Down
4 changes: 2 additions & 2 deletions meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ option('wx_version', type: 'string', value: '3.0.0', description: 'The minimum w

option('credit', type: 'string', value: '', description: 'Build credit shown in program title')

option('enable_update_checker', type: 'boolean', value: false, description: 'Enable the update checker')
option('update_server', type: 'string', value: 'updates.aegisub.org', description: 'Server to use for the update checker')
option('enable_update_checker', type: 'boolean', value: true, description: 'Enable the update checker')
option('update_server', type: 'string', value: 'https://updates.aegisub.org', description: 'Server to use for the update checker')
option('update_url', type: 'string', value: '/trunk', description: 'Base path to use for the update checker')

option('build_osx_bundle', type: 'boolean', value: 'false', description: 'Package Aegisub.app on OSX')
Expand Down
81 changes: 41 additions & 40 deletions src/dialog_version_check.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@

#ifdef WITH_UPDATE_CHECKER

#ifdef _MSC_VER
#pragma warning(disable : 4250) // 'boost::asio::basic_socket_iostream<Protocol>' : inherits 'std::basic_ostream<_Elem,_Traits>::std::basic_ostream<_Elem,_Traits>::_Add_vtordisp2' via dominance
#endif

#include "compat.h"
#include "format.h"
#include "options.h"
Expand All @@ -46,9 +42,10 @@
#include <libaegisub/split.h>

#include <ctime>
#include <boost/asio/ip/tcp.hpp>
#include <curl/curl.h>
#include <functional>
#include <mutex>
#include <sstream>
#include <vector>
#include <wx/button.h>
#include <wx/checkbox.h>
Expand Down Expand Up @@ -280,44 +277,48 @@ static wxString GetAegisubLanguage() {
return to_wx(OPT_GET("App/Language")->GetString());
}

size_t writeToStringCb(char *contents, size_t size, size_t nmemb, std::string *s) {
s->append(contents, size * nmemb);
return size * nmemb;
}

void DoCheck(bool interactive) {
boost::asio::ip::tcp::iostream stream;
stream.connect(UPDATE_CHECKER_SERVER, "http");
if (!stream)
throw VersionCheckError(from_wx(_("Could not connect to updates server.")));

agi::format(stream,
"GET %s?rev=%d&rel=%d&os=%s&lang=%s&aegilang=%s HTTP/1.0\r\n"
"User-Agent: Aegisub %s\r\n"
"Host: %s\r\n"
"Accept: */*\r\n"
"Connection: close\r\n\r\n"
, UPDATE_CHECKER_BASE_URL
, GetSVNRevision()
, (GetIsOfficialRelease() ? 1 : 0)
, GetOSShortName()
, GetSystemLanguage()
, GetAegisubLanguage()
, GetAegisubLongVersionString()
, UPDATE_CHECKER_SERVER);

std::string http_version;
stream >> http_version;
int status_code;
stream >> status_code;
if (!stream || http_version.substr(0, 5) != "HTTP/")
throw VersionCheckError(from_wx(_("Could not download from updates server.")));
if (status_code != 200)
throw VersionCheckError(agi::format(_("HTTP request failed, got HTTP response %d."), status_code));

stream.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

// Skip the headers since we don't care about them
for (auto const& header : agi::line_iterator<std::string>(stream))
if (header.empty()) break;
CURL *curl;
CURLcode res_code;

curl = curl_easy_init();
if(!curl)
throw VersionCheckError(from_wx(_("Curl could not be initialized.")));

curl_easy_setopt(curl, CURLOPT_URL,
agi::format("%s%s?rev=%d&rel=%d&os=%s&lang=%s&aegilang=%s"
, UPDATE_CHECKER_SERVER
, UPDATE_CHECKER_BASE_URL
, GetSVNRevision()
, (GetIsOfficialRelease() ? 1 : 0)
, GetOSShortName()
, GetSystemLanguage()
, GetAegisubLanguage()
).c_str());
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_USERAGENT, agi::format("Aegisub %s", GetAegisubLongVersionString()).c_str());

std::string result;
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeToStringCb);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &result);

res_code = curl_easy_perform(curl);
if(res_code != CURLE_OK) {
std::string err_msg = agi::format(_("Checking for updates failed: %s."), curl_easy_strerror(res_code));
curl_easy_cleanup(curl);
throw VersionCheckError(err_msg);
}

curl_easy_cleanup(curl);

std::stringstream ss(result);
std::vector<AegisubUpdateDescription> results;
for (auto const& line : agi::line_iterator<std::string>(stream)) {
for (auto const& line : agi::line_iterator<std::string>(ss)) {
if (line.empty()) continue;

std::vector<std::string> parsed;
Expand Down
9 changes: 9 additions & 0 deletions subprojects/curl.wrap
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[wrap-file]
directory = curl-7.82.0
source_url = https://github.com/curl/curl/releases/download/curl-7_82_0/curl-7.82.0.tar.gz
source_filename = curl-7.82.0.tar.xz
source_hash = 910cc5fe279dc36e2cca534172c94364cf3fcf7d6494ba56e6c61a390881ddce
patch_directory = curl

[provide]
dependency_names = libcurl
6 changes: 6 additions & 0 deletions subprojects/curl_meson.wrap
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[wrap-file]
directory = curl-7.82.0
source_url = https://github.com/curl/curl/releases/download/curl-7_82_0/curl-7.82.0.tar.gz
source_filename = curl-7.82.0.tar.xz
source_hash = 910cc5fe279dc36e2cca534172c94364cf3fcf7d6494ba56e6c61a390881ddce
patch_directory = curl
3 changes: 3 additions & 0 deletions subprojects/packagefiles/curl/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
project('curl_meson', 'cpp')

libcurl_fixed_inc = include_directories('include/')

0 comments on commit 2f56d11

Please sign in to comment.