738 lines
23 KiB
C
738 lines
23 KiB
C
/* PIKA - Photo and Image Kooker Application
|
|
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
|
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
|
*
|
|
* Original copyright, applying to most contents (license remains unchanged):
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
*
|
|
* pika-update.c
|
|
* Copyright (C) 2019 Jehan
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <glib.h>
|
|
#include <json-glib/json-glib.h>
|
|
#include <stdio.h>
|
|
|
|
#ifdef PLATFORM_OSX
|
|
#import <Foundation/Foundation.h>
|
|
#endif /* PLATFORM_OSX */
|
|
|
|
#ifndef PIKA_CONSOLE_COMPILATION
|
|
#include <gtk/gtk.h>
|
|
#endif
|
|
|
|
#include "libpikabase/pikabase.h"
|
|
|
|
#include "core/core-types.h"
|
|
|
|
#include "config/pikacoreconfig.h"
|
|
|
|
#ifndef PIKA_CONSOLE_COMPILATION
|
|
#include "dialogs/about-dialog.h"
|
|
#include "dialogs/welcome-dialog.h"
|
|
#endif
|
|
|
|
#include "pika-intl.h"
|
|
#include "pika-update.h"
|
|
#include "pika-version.h"
|
|
|
|
static gboolean pika_update_known (PikaCoreConfig *config,
|
|
const gchar *last_version,
|
|
gint64 release_timestamp,
|
|
gint build_revision,
|
|
const gchar *comment);
|
|
static void pika_check_updates_process (const gchar *source,
|
|
gchar *file_contents,
|
|
gsize file_length,
|
|
PikaCoreConfig *config);
|
|
#ifndef PLATFORM_OSX
|
|
static void pika_check_updates_callback (GObject *source,
|
|
GAsyncResult *result,
|
|
gpointer user_data);
|
|
#endif /* PLATFORM_OSX */
|
|
static void pika_update_about_dialog (PikaCoreConfig *config,
|
|
const GParamSpec *pspec,
|
|
gpointer user_data);
|
|
|
|
static gboolean pika_version_break (const gchar *v,
|
|
gint *major,
|
|
gint *minor,
|
|
gint *micro);
|
|
static gint pika_version_cmp (const gchar *v1,
|
|
const gchar *v2);
|
|
|
|
static const gchar * pika_get_version_url (void);
|
|
|
|
#ifdef PLATFORM_OSX
|
|
static gint pika_check_updates_process_idle (gpointer data);
|
|
#endif
|
|
|
|
/* Private Functions */
|
|
|
|
/**
|
|
* pika_update_known:
|
|
* @config:
|
|
* @last_version:
|
|
* @release_timestamp: must be non-zero is @last_version is not %NULL.
|
|
* @build_revision:
|
|
* @build_comment:
|
|
*
|
|
* Compare @last_version with currently running version. If the checked
|
|
* version is more recent than running version, then @config properties
|
|
* are updated appropriately (which may trigger a dialog depending on
|
|
* update policy settings).
|
|
* If @last_version is %NULL, the currently stored "last known release"
|
|
* is compared. Even if we haven't made any new remote checks, it is
|
|
* important to always compare again stored last release, otherwise we
|
|
* might warn of the same current version, or worse an older version.
|
|
*
|
|
* Returns: %TRUE is @last_version (or stored last known release if
|
|
* @last_version was %NULL) is newer than running version.
|
|
*/
|
|
static gboolean
|
|
pika_update_known (PikaCoreConfig *config,
|
|
const gchar *last_version,
|
|
gint64 release_timestamp,
|
|
gint build_revision,
|
|
const gchar *build_comment)
|
|
{
|
|
gboolean new_check = (last_version != NULL);
|
|
|
|
if (last_version && release_timestamp == 0)
|
|
{
|
|
/* I don't exit with a g_return_val_if_fail() assert because this
|
|
* is not necessarily a code bug. It may be data issues. So let's
|
|
* just return with an error printed on stderr.
|
|
*/
|
|
g_printerr ("%s: version %s with no release dates.\n",
|
|
G_STRFUNC, last_version);
|
|
return FALSE;
|
|
}
|
|
|
|
if (last_version == NULL)
|
|
{
|
|
last_version = config->last_known_release;
|
|
release_timestamp = config->last_release_timestamp;
|
|
build_revision = config->last_revision;
|
|
build_comment = config->last_release_comment;
|
|
}
|
|
|
|
if (last_version &&
|
|
(/* We are using a newer version than last check. This could
|
|
* happen if updating the config files without having
|
|
* re-checked the remote JSON file.
|
|
*/
|
|
pika_version_cmp (last_version, NULL) < 0 ||
|
|
/* Already using the last officially released
|
|
* revision. */
|
|
(pika_version_cmp (last_version, NULL) == 0 &&
|
|
build_revision <= pika_version_get_revision ())))
|
|
{
|
|
last_version = NULL;
|
|
}
|
|
|
|
if (last_version == NULL)
|
|
{
|
|
release_timestamp = 0;
|
|
build_revision = 0;
|
|
build_comment = NULL;
|
|
}
|
|
|
|
if (new_check)
|
|
g_object_set (config,
|
|
"check-update-timestamp", g_get_real_time() / G_USEC_PER_SEC,
|
|
NULL);
|
|
|
|
g_object_set (config,
|
|
"last-release-timestamp", release_timestamp,
|
|
"last-known-release", last_version,
|
|
"last-revision", build_revision,
|
|
"last-release-comment", build_comment,
|
|
NULL);
|
|
|
|
/* Are we running an old PIKA? */
|
|
return (last_version != NULL);
|
|
}
|
|
|
|
static gboolean
|
|
pika_update_get_highest (JsonParser *parser,
|
|
gchar **highest_version,
|
|
gint64 *release_timestamp,
|
|
gint *build_revision,
|
|
gchar **build_comment,
|
|
gboolean unstable)
|
|
{
|
|
JsonPath *path;
|
|
JsonNode *result;
|
|
JsonArray *versions;
|
|
const gchar *platform;
|
|
const gchar *path_str;
|
|
const gchar *release_date = NULL;
|
|
GError *error = NULL;
|
|
gint i;
|
|
|
|
g_return_val_if_fail (highest_version != NULL, FALSE);
|
|
g_return_val_if_fail (release_timestamp != NULL, FALSE);
|
|
g_return_val_if_fail (build_revision != NULL, FALSE);
|
|
g_return_val_if_fail (build_comment != NULL, FALSE);
|
|
|
|
*highest_version = NULL;
|
|
*release_timestamp = 0;
|
|
*build_revision = 0;
|
|
*build_comment = NULL;
|
|
|
|
if (unstable)
|
|
path_str = "$['DEVELOPMENT'][*]";
|
|
else
|
|
path_str = "$['STABLE'][*]";
|
|
|
|
/* For Windows and macOS, let's look if installers are available.
|
|
* For other platforms, let's just look for source release.
|
|
*/
|
|
if (g_strcmp0 (PIKA_BUILD_PLATFORM_FAMILY, "windows") == 0 ||
|
|
g_strcmp0 (PIKA_BUILD_PLATFORM_FAMILY, "macos") == 0)
|
|
platform = PIKA_BUILD_PLATFORM_FAMILY;
|
|
else
|
|
platform = "source";
|
|
|
|
path = json_path_new ();
|
|
/* Ideally we could just use Json path filters like this to
|
|
* retrieve only released binaries for a given platform:
|
|
* g_strdup_printf ("$['STABLE'][?(@.%s)]['version']", platform);
|
|
* json_array_get_string_element (result, 0);
|
|
* And that would be it! We'd have our last release for given
|
|
* platform.
|
|
* Unfortunately json-glib does not support filter syntax, so we
|
|
* end up looping through releases.
|
|
*/
|
|
if (! json_path_compile (path, path_str, &error))
|
|
{
|
|
g_warning ("%s: path compilation failed: %s\n",
|
|
G_STRFUNC, error->message);
|
|
g_clear_error (&error);
|
|
g_object_unref (path);
|
|
|
|
return FALSE;
|
|
}
|
|
result = json_path_match (path, json_parser_get_root (parser));
|
|
if (! JSON_NODE_HOLDS_ARRAY (result))
|
|
{
|
|
g_printerr ("%s: match for \"%s\" is not a JSON array.\n",
|
|
G_STRFUNC, path_str);
|
|
g_object_unref (path);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
versions = json_node_get_array (result);
|
|
for (i = 0; i < (gint) json_array_get_length (versions); i++)
|
|
{
|
|
JsonObject *version;
|
|
|
|
/* Note that we don't actually look for the highest version,
|
|
* but for the highest version for which a build for your
|
|
* platform (and optional build-id) is available.
|
|
*
|
|
* So we loop through the version list then the build array
|
|
* and break at first compatible release, since JSON arrays
|
|
* are ordered.
|
|
*/
|
|
version = json_array_get_object_element (versions, i);
|
|
if (json_object_has_member (version, platform))
|
|
{
|
|
JsonArray *builds;
|
|
gint j;
|
|
|
|
builds = json_object_get_array_member (version, platform);
|
|
|
|
for (j = 0; j < (gint) json_array_get_length (builds); j++)
|
|
{
|
|
const gchar *build_id = NULL;
|
|
JsonObject *build;
|
|
|
|
build = json_array_get_object_element (builds, j);
|
|
if (json_object_has_member (build, "build-id"))
|
|
build_id = json_object_get_string_member (build, "build-id");
|
|
if (g_strcmp0 (build_id, PIKA_BUILD_ID) == 0 ||
|
|
g_strcmp0 (platform, "source") == 0)
|
|
{
|
|
/* Release date is the build date if any set,
|
|
* otherwise the main version release date.
|
|
*/
|
|
if (json_object_has_member (build, "date"))
|
|
release_date = json_object_get_string_member (build, "date");
|
|
else
|
|
release_date = json_object_get_string_member (version, "date");
|
|
|
|
/* These are optional data. */
|
|
if (json_object_has_member (build, "revision"))
|
|
{
|
|
if (g_strcmp0 (json_node_type_name (json_object_get_member (build, "revision")),
|
|
"String") == 0)
|
|
*build_revision = g_ascii_strtoull (json_object_get_string_member (build, "revision"),
|
|
NULL, 10);
|
|
else
|
|
*build_revision = json_object_get_int_member (build, "revision");
|
|
}
|
|
if (json_object_has_member (build, "comment"))
|
|
*build_comment = g_strdup (json_object_get_string_member (build, "comment"));
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (release_date)
|
|
{
|
|
*highest_version = g_strdup (json_object_get_string_member (version, "version"));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (*highest_version && *release_date)
|
|
{
|
|
GDateTime *datetime;
|
|
gchar *str;
|
|
|
|
str = g_strdup_printf ("%s 00:00:00Z", release_date);
|
|
datetime = g_date_time_new_from_iso8601 (str, NULL);
|
|
g_free (str);
|
|
|
|
if (datetime)
|
|
{
|
|
*release_timestamp = g_date_time_to_unix (datetime);
|
|
g_date_time_unref (datetime);
|
|
}
|
|
else
|
|
{
|
|
/* JSON file data bug. */
|
|
g_printerr ("%s: release date for version %s not properly formatted: %s\n",
|
|
G_STRFUNC, *highest_version, release_date);
|
|
|
|
g_clear_pointer (highest_version, g_free);
|
|
g_clear_pointer (build_comment, g_free);
|
|
*build_revision = 0;
|
|
}
|
|
}
|
|
|
|
json_node_unref (result);
|
|
g_object_unref (path);
|
|
|
|
return (*highest_version != NULL);
|
|
}
|
|
|
|
static void
|
|
pika_check_updates_process (const gchar *source,
|
|
gchar *file_contents,
|
|
gsize file_length,
|
|
PikaCoreConfig *config)
|
|
{
|
|
gchar *last_version = NULL;
|
|
gchar *build_comment = NULL;
|
|
gint64 release_timestamp = 0;
|
|
gint build_revision = 0;
|
|
GError *error = NULL;
|
|
JsonParser *parser;
|
|
|
|
parser = json_parser_new ();
|
|
if (! json_parser_load_from_data (parser, file_contents, file_length, &error))
|
|
{
|
|
gchar *uri = g_file_get_uri (G_FILE (source));
|
|
|
|
g_printerr ("%s: parsing of %s failed: %s\n", G_STRFUNC,
|
|
uri, error->message);
|
|
|
|
g_free (uri);
|
|
g_free (file_contents);
|
|
g_clear_object (&parser);
|
|
g_clear_error (&error);
|
|
|
|
return;
|
|
}
|
|
|
|
pika_update_get_highest (parser, &last_version, &release_timestamp,
|
|
&build_revision, &build_comment, FALSE);
|
|
|
|
#ifdef PIKA_UNSTABLE
|
|
{
|
|
gchar *dev_version = NULL;
|
|
gchar *dev_comment = NULL;
|
|
gint64 dev_timestamp = 0;
|
|
gint dev_revision = 0;
|
|
|
|
pika_update_get_highest (parser, &dev_version, &dev_timestamp,
|
|
&dev_revision, &dev_comment, TRUE);
|
|
if (dev_version)
|
|
{
|
|
if (! last_version || pika_version_cmp (dev_version, last_version) > 0)
|
|
{
|
|
g_clear_pointer (&last_version, g_free);
|
|
g_clear_pointer (&build_comment, g_free);
|
|
last_version = dev_version;
|
|
build_comment = dev_comment;
|
|
release_timestamp = dev_timestamp;
|
|
build_revision = dev_revision;
|
|
}
|
|
else
|
|
{
|
|
g_clear_pointer (&dev_version, g_free);
|
|
g_clear_pointer (&dev_comment, g_free);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
pika_update_known (config, last_version, release_timestamp, build_revision, build_comment);
|
|
|
|
g_clear_pointer (&last_version, g_free);
|
|
g_clear_pointer (&build_comment, g_free);
|
|
g_object_unref (parser);
|
|
g_free (file_contents);
|
|
}
|
|
|
|
#ifndef PLATFORM_OSX
|
|
static void
|
|
pika_check_updates_callback (GObject *source,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
PikaCoreConfig *config = user_data;
|
|
char *file_contents = NULL;
|
|
gsize file_length = 0;
|
|
GError *error = NULL;
|
|
|
|
if (g_file_load_contents_finish (G_FILE (source), result,
|
|
&file_contents, &file_length,
|
|
NULL, &error))
|
|
{
|
|
pika_check_updates_process (g_file_get_uri (G_FILE (source)), file_contents, file_length, config);
|
|
}
|
|
else
|
|
{
|
|
gchar *uri = g_file_get_uri (G_FILE (source));
|
|
|
|
g_printerr ("%s: loading of %s failed: %s\n", G_STRFUNC,
|
|
uri, error->message);
|
|
|
|
g_free (uri);
|
|
g_clear_error (&error);
|
|
}
|
|
}
|
|
#endif /* PLATFORM_OSX */
|
|
|
|
static void
|
|
pika_update_about_dialog (PikaCoreConfig *config,
|
|
const GParamSpec *pspec,
|
|
gpointer user_data)
|
|
{
|
|
#ifndef PIKA_CONSOLE_COMPILATION
|
|
Pika *pika = user_data;
|
|
#endif
|
|
|
|
g_signal_handlers_disconnect_by_func (config,
|
|
(GCallback) pika_update_about_dialog,
|
|
user_data);
|
|
|
|
if (config->last_known_release != NULL)
|
|
{
|
|
#ifndef PIKA_CONSOLE_COMPILATION
|
|
gtk_widget_show (about_dialog_create (pika));
|
|
#else
|
|
g_printerr (_("A new version of PIKA (%s) was released.\n"
|
|
"It is recommended to update."),
|
|
config->last_known_release);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
pika_version_break (const gchar *v,
|
|
gint *major,
|
|
gint *minor,
|
|
gint *micro)
|
|
{
|
|
gchar **versions;
|
|
|
|
*major = 0;
|
|
*minor = 0;
|
|
*micro = 0;
|
|
|
|
if (v == NULL)
|
|
return FALSE;
|
|
|
|
versions = g_strsplit_set (v, ".", 3);
|
|
if (versions[0] != NULL)
|
|
{
|
|
*major = g_ascii_strtoll (versions[0], NULL, 10);
|
|
if (versions[1] != NULL)
|
|
{
|
|
*minor = g_ascii_strtoll (versions[1], NULL, 10);
|
|
if (versions[2] != NULL)
|
|
{
|
|
*micro = g_ascii_strtoll (versions[2], NULL, 10);
|
|
}
|
|
}
|
|
}
|
|
g_strfreev (versions);
|
|
|
|
return (*major > 0 || *minor > 0 || *micro > 0);
|
|
}
|
|
|
|
/**
|
|
* pika_version_cmp:
|
|
* @v1: a string representing a version, ex. "2.10.22".
|
|
* @v2: a string representing another version, ex. "2.99.2".
|
|
*
|
|
* If @v2 is %NULL, @v1 is compared to the currently running version.
|
|
*
|
|
* Returns: an integer less than, equal to, or greater than zero if @v1
|
|
* is found to represent a version respectively, lower than,
|
|
* matching, or greater than @v2.
|
|
*/
|
|
static gint
|
|
pika_version_cmp (const gchar *v1,
|
|
const gchar *v2)
|
|
{
|
|
gint major1;
|
|
gint minor1;
|
|
gint micro1;
|
|
gint major2 = PIKA_MAJOR_VERSION;
|
|
gint minor2 = PIKA_MINOR_VERSION;
|
|
gint micro2 = PIKA_MICRO_VERSION;
|
|
|
|
g_return_val_if_fail (v1 != NULL, -1);
|
|
|
|
if (! pika_version_break (v1, &major1, &minor1, µ1))
|
|
{
|
|
/* If version is not properly parsed, something is wrong with
|
|
* upstream version number or parsing. This should not happen.
|
|
*/
|
|
g_printerr ("%s: version not properly formatted: %s\n",
|
|
G_STRFUNC, v1);
|
|
|
|
return -1;
|
|
}
|
|
if (v2 && ! pika_version_break (v2, &major2, &minor2, µ2))
|
|
{
|
|
g_printerr ("%s: version not properly formatted: %s\n",
|
|
G_STRFUNC, v2);
|
|
|
|
return 1;
|
|
}
|
|
|
|
if (major1 == major2 && minor1 == minor2 && micro1 == micro2)
|
|
return 0;
|
|
else if (major1 > major2 ||
|
|
(major1 == major2 && minor1 > minor2) ||
|
|
(major1 == major2 && minor1 == minor2 && micro1 > micro2))
|
|
return 1;
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
static const gchar *
|
|
pika_get_version_url (void)
|
|
{
|
|
#ifdef PIKA_RELEASE
|
|
return "https://www.pika.technology.heckin_versions.json";
|
|
#else
|
|
if (g_getenv ("PIKA_DEV_VERSIONS_JSON"))
|
|
return g_getenv ("PIKA_DEV_VERSIONS_JSON");
|
|
else
|
|
return "https://testing.pika.technology.heckin_versions.json";
|
|
#endif
|
|
}
|
|
|
|
#ifdef PLATFORM_OSX
|
|
typedef struct _PikaCheckUpdatesData
|
|
{
|
|
const gchar *pika_versions;
|
|
gchar *json_result;
|
|
gsize json_size;
|
|
PikaCoreConfig *config;
|
|
} PikaCheckUpdatesData;
|
|
|
|
static int
|
|
pika_check_updates_process_idle (gpointer data)
|
|
{
|
|
PikaCheckUpdatesData *check_updates_data = (PikaCheckUpdatesData *) data;
|
|
|
|
pika_check_updates_process (check_updates_data->pika_versions,
|
|
check_updates_data->json_result,
|
|
check_updates_data->json_size,
|
|
check_updates_data->config);
|
|
|
|
g_free (check_updates_data);
|
|
|
|
return FALSE; /* remove idle */
|
|
}
|
|
#endif /* PLATFORM_OSX */
|
|
|
|
/* Public Functions */
|
|
|
|
/*
|
|
* pika_update_auto_check:
|
|
* @config:
|
|
* @pika:
|
|
*
|
|
* Run the check for newer versions of PIKA if conditions are right.
|
|
*
|
|
* Returns: %TRUE if a check was actually run.
|
|
*/
|
|
gboolean
|
|
pika_update_auto_check (PikaCoreConfig *config,
|
|
Pika *pika)
|
|
{
|
|
gint64 prev_update_timestamp;
|
|
gint64 current_timestamp;
|
|
|
|
if (config->config_version == NULL ||
|
|
pika_version_cmp (PIKA_VERSION,
|
|
config->config_version) > 0)
|
|
{
|
|
#ifndef PIKA_CONSOLE_COMPILATION
|
|
/* PIKA was just updated and this is the first time the new
|
|
* version is run. Display a welcome dialog, and do not check for
|
|
* updates right now. */
|
|
gtk_widget_show (welcome_dialog_create (pika));
|
|
|
|
return FALSE;
|
|
#else
|
|
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE,
|
|
"Welcome to PIKA %s!", PIKA_VERSION);
|
|
#endif
|
|
}
|
|
|
|
/* Builds with update check deactivated just always return FALSE. */
|
|
#ifdef CHECK_UPDATE
|
|
/* Allows to disable updates at package level with a build having the
|
|
* version check code built-in.
|
|
* For instance, it would allow to use the same Windows installer for
|
|
* the Windows Store (with update check disabled because it comes with
|
|
* its own update channel).
|
|
*/
|
|
if (! pika_version_check_update () ||
|
|
! config->check_updates)
|
|
#endif
|
|
return FALSE;
|
|
|
|
g_object_get (config,
|
|
"check-update-timestamp", &prev_update_timestamp,
|
|
NULL);
|
|
current_timestamp = g_get_real_time() / G_USEC_PER_SEC;
|
|
|
|
/* Get rid of invalid saved timestamps. */
|
|
if (prev_update_timestamp > current_timestamp)
|
|
prev_update_timestamp = -1;
|
|
|
|
#ifdef PIKA_RELEASE
|
|
/* Do not check more than once a week. */
|
|
if (current_timestamp - prev_update_timestamp < 3600L * 24L * 7L)
|
|
return FALSE;
|
|
#endif
|
|
|
|
g_signal_connect (config, "notify::last-known-release",
|
|
(GCallback) pika_update_about_dialog,
|
|
pika);
|
|
|
|
pika_update_check (config);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* pika_update_check:
|
|
* @config:
|
|
*
|
|
* Run the check for newer versions of PIKA inconditionnally.
|
|
*/
|
|
void
|
|
pika_update_check (PikaCoreConfig *config)
|
|
{
|
|
#ifdef PLATFORM_OSX
|
|
const gchar *pika_versions;
|
|
|
|
pika_versions = pika_get_version_url ();
|
|
|
|
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
|
|
[request setURL:[NSURL URLWithString:@(pika_versions)]];
|
|
[request setHTTPMethod:@"GET"];
|
|
|
|
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
|
|
/* completionHandler is called on a background thread */
|
|
[[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
|
|
NSString *reply;
|
|
gchar *json_result;
|
|
PikaCheckUpdatesData *update_results;
|
|
|
|
if (error)
|
|
{
|
|
g_printerr ("%s: pika_update_check failed to get update from %s, with error: %s\n",
|
|
G_STRFUNC,
|
|
pika_versions,
|
|
[error.localizedDescription UTF8String]);
|
|
return;
|
|
}
|
|
|
|
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
|
|
NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
|
|
|
|
if (statusCode != 200)
|
|
{
|
|
g_printerr ("%s: pika_update_check failed to get update from %s, with status code: %d\n",
|
|
G_STRFUNC,
|
|
pika_versions,
|
|
(int)statusCode);
|
|
return;
|
|
}
|
|
}
|
|
|
|
reply = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
|
json_result = g_strdup ([reply UTF8String]); /* will be freed by pika_check_updates_process */
|
|
|
|
update_results = g_new (PikaCheckUpdatesData, 1);
|
|
|
|
update_results->pika_versions = pika_versions;
|
|
update_results->json_result = json_result;
|
|
update_results->json_size = [reply lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
|
|
update_results->config = config;
|
|
|
|
g_idle_add ((GSourceFunc) pika_check_updates_process_idle, (gpointer) update_results);
|
|
}] resume];
|
|
#else
|
|
GFile *pika_versions;
|
|
|
|
pika_versions = g_file_new_for_uri (pika_get_version_url ());
|
|
|
|
g_file_load_contents_async (pika_versions, NULL, pika_check_updates_callback, config);
|
|
g_object_unref (pika_versions);
|
|
#endif /* PLATFORM_OSX */
|
|
}
|
|
|
|
/*
|
|
* pika_update_refresh:
|
|
* @config:
|
|
*
|
|
* Do not execute a remote check, but refresh the known release data as
|
|
* it may be outdated.
|
|
*/
|
|
void
|
|
pika_update_refresh (PikaCoreConfig *config)
|
|
{
|
|
pika_update_known (config, NULL, 0, 0, NULL);
|
|
}
|