Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

updatechecker: Port to GIO and small other fixes #1340

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build/updatechecker.m4
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ AC_DEFUN([GP_CHECK_UPDATECHECKER],
GP_ARG_DISABLE([Updatechecker], [auto])

GP_CHECK_PLUGIN_DEPS([Updatechecker], UPDATECHECKER,
[libsoup-2.4 >= 2.42])
[gio-2.0 >= 2.44])

GP_COMMIT_PLUGIN_STATUS([Updatechecker])

Expand Down
6 changes: 3 additions & 3 deletions updatechecker/README
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ plugins. This has potential to plague you with Geany's new version.
Requirements
------------

Updatechecker depends on a recent version of Geany (0.20 or above)
Updatechecker depends on a recent version of Geany (1.25 or above)
as well as on:

* GTK >= 2.12
* libsoup 2.4 >= 2.42
* GTK >= 3.0
* GIO >= 2.44

To compile it on your own you will need the devel packages for these.

Expand Down
145 changes: 104 additions & 41 deletions updatechecker/src/updatechecker.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@

/* A little plugin for regular checks for updates of Geany */

#include "libsoup/soup.h"
#include "stdlib.h"
#include <stdlib.h>
#include <gio/gio.h>

#ifdef HAVE_CONFIG_H
#include "config.h" /* for the gettext domain */
Expand Down Expand Up @@ -50,14 +50,16 @@ enum {
#define UPDATE_CHECK_URL "https://geany.org/service/version/"

static GtkWidget *main_menu_item = NULL;
static void update_check_result_cb(SoupSession *session,
SoupMessage *msg, gpointer user_data);
static void update_check_result(gint type, const gchar *remote_version,
GError *err);

static gboolean check_on_startup = FALSE;

/* Configuration file */
static gchar *config_file = NULL;

static GCancellable *cancellable = NULL;


static struct
{
Expand All @@ -75,27 +77,87 @@ typedef struct
version_struct;


static void update_check(gint type)
typedef struct {
GFile *file;
GFileInputStream *stream;
gchar buffer[32];
int update_type;
} ReadData;


static void read_data_free(ReadData *data)
{
SoupSession *soup;
SoupMessage *msg;
gchar *user_agent = g_strconcat("Updatechecker ", VERSION, " at Geany ",
GEANY_VERSION, NULL);
g_clear_object(&data->file);
g_clear_object(&data->stream);
g_free(data);
}

g_message("Checking for updates (querying URL \"%s\")", UPDATE_CHECK_URL);
soup = soup_session_new_with_options(
SOUP_SESSION_USER_AGENT, user_agent,
SOUP_SESSION_TIMEOUT, 10,
NULL);

g_free(user_agent);
static void stream_read_all_ready(GObject *stream, GAsyncResult *result, gpointer user_data)
{
ReadData *data = user_data;
gsize bytes_read;
GError *err = NULL;

if (! g_input_stream_read_all_finish(G_INPUT_STREAM(stream), result, &bytes_read, &err))
{
update_check_result(data->update_type, NULL, err);
g_error_free(err);
}
else
{
g_warn_if_fail(bytes_read < G_N_ELEMENTS(data->buffer));
data->buffer[MIN(bytes_read, G_N_ELEMENTS(data->buffer) - 1)] = 0;
update_check_result(data->update_type, data->buffer, err);
}
read_data_free(data);
}


msg = soup_message_new ("GET", UPDATE_CHECK_URL);
static void file_read_ready(GObject *file, GAsyncResult *result, gpointer user_data)
{
ReadData *data = user_data;
GError *err = NULL;

soup_session_queue_message (soup, msg, update_check_result_cb, GINT_TO_POINTER(type));
data->stream = g_file_read_finish(G_FILE(file), result, &err);
if (! data->stream)
{
update_check_result(data->update_type, NULL, err);
g_error_free(err);
read_data_free(data);
}
else
{
g_input_stream_read_all_async(G_INPUT_STREAM(data->stream),
data->buffer,
G_N_ELEMENTS(data->buffer) - 1,
G_PRIORITY_DEFAULT, cancellable,
stream_read_all_ready, data);
}
}


static void update_check(gint type)
{
ReadData *data;

g_message("Checking for updates (querying URL \"%s\")", UPDATE_CHECK_URL);

/* cancel any current update check */
if (cancellable)
{
g_cancellable_cancel(cancellable);
g_object_unref(cancellable);
}
cancellable = g_cancellable_new();

data = g_malloc0(sizeof *data);
data->update_type = type;
data->file = g_file_new_for_uri(UPDATE_CHECK_URL);
g_file_read_async (data->file, G_PRIORITY_DEFAULT, cancellable,
file_read_ready, data);
}


static void
on_geany_startup_complete(G_GNUC_UNUSED GObject *obj,
Expand Down Expand Up @@ -185,15 +247,27 @@ version_compare(const gchar *current_version)
}


static void update_check_result_cb(SoupSession *session,
SoupMessage *msg, gpointer user_data)
static void update_check_result(gint type, const gchar *remote_version, GError *err)
{
gint type = GPOINTER_TO_INT(user_data);

/* Checking whether we did get a valid (200) result */
if (msg->status_code == 200)
if (g_error_matches(err, G_IO_ERROR, G_IO_ERROR_CANCELLED))
; /* nothing to do */
else if (err)
{
gchar *error_message = g_strdup_printf(
_("Unable to perform version check: %s"), err->message);
if (type == UPDATECHECK_MANUAL)
{
dialogs_show_msgbox(GTK_MESSAGE_ERROR, "%s", error_message);
}
else
{
msgwin_status_add("%s", error_message);
}
g_warning("%s", error_message);
g_free(error_message);
}
else
{
const gchar *remote_version = msg->response_body->data;
if (version_compare(remote_version) == TRUE)
{
gchar *update_msg = g_strdup_printf(
Expand All @@ -217,22 +291,6 @@ static void update_check_result_cb(SoupSession *session,
g_message("%s", no_update_msg);
}
}
else
{
gchar *error_message = g_strdup_printf(
_("Unable to perform version check.\nError code: %d \nError message: »%s«"),
msg->status_code, msg->reason_phrase);
if (type == UPDATECHECK_MANUAL)
{
dialogs_show_msgbox(GTK_MESSAGE_ERROR, "%s", error_message);
}
else
{
msgwin_status_add("%s", error_message);
}
g_warning("Connection error: Code: %d; Message: %s", msg->status_code, msg->reason_phrase);
g_free(error_message);
}
}

static void manual_check_activated_cb(GtkMenuItem *menuitem, gpointer gdata)
Expand Down Expand Up @@ -285,7 +343,7 @@ GtkWidget *
plugin_configure(GtkDialog * dialog)
{
GtkWidget *vbox;
vbox = gtk_vbox_new(FALSE, 6);
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);

config_widgets.run_on_startup = gtk_check_button_new_with_label(
_("Run updatecheck on startup"));
Expand Down Expand Up @@ -341,6 +399,11 @@ void plugin_init(GeanyData *data)

void plugin_cleanup(void)
{
if (cancellable)
{
g_cancellable_cancel(cancellable);
g_clear_object(&cancellable);
}
gtk_widget_destroy(main_menu_item);
g_free(config_file);
}