27#include <json-glib/json-glib.h>
31#define DT_UPDATES_ENABLED_KEY "updates/enabled"
32#define DT_UPDATES_LAST_CHECK_KEY "updates/last_check"
33#define DT_UPDATES_MANIFEST_KEY "updates/manifest_url"
34#define DT_UPDATES_INTERVAL (24 * 60 * 60)
36#define DT_UPDATES_MAX_BODY (1 << 20)
47 if(g_getenv(
"APPIMAGE"))
return "appimage";
49 if(g_file_test(
"/.flatpak-info", G_FILE_TEST_EXISTS))
return "flatpak";
51#if defined(__aarch64__) || defined(__arm64__)
73static size_t _write_cb(
char *data,
size_t size,
size_t nmemb,
void *user)
75 GString *body = (GString *)user;
76 const size_t n =
size * nmemb;
78 g_string_append_len(body, data,
n);
104 return G_SOURCE_REMOVE;
110 JsonParser *parser = json_parser_new();
112 if(json_parser_load_from_data(parser, body, len, NULL))
114 JsonNode *root = json_parser_get_root(parser);
115 JsonObject *
top = JSON_NODE_HOLDS_OBJECT(root) ? json_node_get_object(root) : NULL;
116 JsonObject *formats = (
top && json_object_has_member(
top,
"formats")) ? json_object_get_object_member(
top,
"formats") : NULL;
118 JsonObject *entry = (formats && format && json_object_has_member(formats, format))
119 ? json_object_get_object_member(formats, format)
123 const char *commit = json_object_has_member(entry,
"commit") ? json_object_get_string_member(entry,
"commit") : NULL;
124 const char *version = json_object_has_member(entry,
"version") ? json_object_get_string_member(entry,
"version") : NULL;
125 const char *url = json_object_has_member(entry,
"url") ? json_object_get_string_member(entry,
"url") : NULL;
130 const gboolean differs = commit && *commit && strncmp(commit,
darktable_commit_hash, strlen(commit)) != 0;
133 differs ?
"newer available" :
"up to date");
137 found->
url = g_strdup(url);
138 found->
version = g_strdup(version ? version :
"unknown");
146 g_object_unref(parser);
153 if(!url || !*url)
return NULL;
155 GString *body = g_string_sized_new(8192);
159 CURL *curl = curl_easy_init();
162 curl_easy_setopt(curl, CURLOPT_URL, url);
163 curl_easy_setopt(curl, CURLOPT_USERAGENT, agent);
164 curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
165 curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 3L);
166 curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5L);
167 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);
168 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
_write_cb);
169 curl_easy_setopt(curl, CURLOPT_WRITEDATA, body);
170#if defined(_WIN32) && defined(CURLSSLOPT_NATIVE_CA)
172 curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, (
long)CURLSSLOPT_NATIVE_CA);
174 const CURLcode
res = curl_easy_perform(curl);
176 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &
status);
177 curl_easy_cleanup(curl);
183 g_main_context_invoke(NULL,
_announce, found);
193 res == CURLE_OK ?
"unexpected status" : curl_easy_strerror(
res),
status);
195 g_string_free(body,
TRUE);
204 if(!have_gui)
return;
208 const gint64 now = (gint64)time(NULL);
int dt_conf_get_bool(const char *name)
void dt_conf_set_int64(const char *name, int64_t val)
int64_t dt_conf_get_int64(const char *name)
64-bit integer for name, clamped to its declared bounds.
const char * dt_conf_get_string_const(const char *name)
Borrow the stored string for name without copying it.
const char darktable_commit_hash[]
const char darktable_package_version[]
GtkWidget * status
result of the last capture
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
const char * dt_updates_get_available_version(void)
void dt_updates_init(const gboolean have_gui, dt_updates_notify_fn notify)
const char * dt_updates_runtime_format(void)
#define DT_UPDATES_ENABLED_KEY
static size_t _write_cb(char *data, size_t size, size_t nmemb, void *user)
#define DT_UPDATES_MAX_BODY
static gpointer _updates_worker(gpointer data)
static _found_t * _evaluate(const char *body, gsize len)
#define DT_UPDATES_INTERVAL
#define DT_UPDATES_MANIFEST_KEY
static char * _available_version
static dt_updates_notify_fn _notify
static gboolean _announce(gpointer data)
void dt_updates_shutdown(void)
const char * dt_updates_get_download_url(void)
static gint _shutting_down
static char * _download_url
#define DT_UPDATES_LAST_CHECK_KEY
The nightly update check.
void(* dt_updates_notify_fn)(const char *version, const char *url)