diff options
author | Daniel Kolesa <dkolesa@igalia.com> | 2021-03-24 15:38:54 +0100 |
---|---|---|
committer | Patrick Griffis <pgriffis@igalia.com> | 2021-10-15 13:48:34 -0500 |
commit | 044c8392e9d1c8a0ae2d3177d8f191eae4def400 (patch) | |
tree | 89faddc963b6f3ca15ecced4b29e34beea3cbad2 | |
parent | b98b97c60450d1b512930d15ce74905a2689e626 (diff) | |
download | libgweather-044c8392e9d1c8a0ae2d3177d8f191eae4def400.tar.gz |
Port to libsoup3
-rw-r--r-- | libgweather/gweather-private.h | 10 | ||||
-rw-r--r-- | libgweather/gweather-weather.c | 33 | ||||
-rw-r--r-- | libgweather/meson.build | 2 | ||||
-rw-r--r-- | libgweather/tests/test_libgweather.c | 26 | ||||
-rw-r--r-- | libgweather/weather-iwin.c | 49 | ||||
-rw-r--r-- | libgweather/weather-metar.c | 88 | ||||
-rw-r--r-- | libgweather/weather-metno.c | 63 | ||||
-rw-r--r-- | libgweather/weather-owm.c | 60 | ||||
-rw-r--r-- | meson.build | 20 | ||||
-rw-r--r-- | meson_options.txt | 2 |
10 files changed, 317 insertions, 36 deletions
diff --git a/libgweather/gweather-private.h b/libgweather/gweather-private.h index f022feb..876ade3 100644 --- a/libgweather/gweather-private.h +++ b/libgweather/gweather-private.h @@ -234,6 +234,16 @@ void _gweather_info_request_done (GWeatherInfo *info, SoupMessage *message); +#if SOUP_CHECK_VERSION (2, 99, 2) +void _gweather_info_queue_request (GWeatherInfo *info, + SoupMessage *message, + GAsyncReadyCallback callback); +#else +void _gweather_info_queue_request (GWeatherInfo *info, + SoupMessage *message, + SoupSessionCallback callback); +#endif + void ecl2equ (double t, double eclipLon, diff --git a/libgweather/gweather-weather.c b/libgweather/gweather-weather.c index 98b3998..7666938 100644 --- a/libgweather/gweather-weather.c +++ b/libgweather/gweather-weather.c @@ -360,7 +360,7 @@ _gweather_info_request_done (GWeatherInfo *info, SoupMessage *message) { info->requests_pending = g_slist_remove (info->requests_pending, message); - g_object_ref (message); + g_object_unref (message); if (info->requests_pending == NULL) { fixup_current_conditions (info); @@ -371,6 +371,29 @@ _gweather_info_request_done (GWeatherInfo *info, } } +#if SOUP_CHECK_VERSION (2, 99, 2) +void +_gweather_info_queue_request (GWeatherInfo *info, + SoupMessage *msg, + GAsyncReadyCallback callback) +{ + GCancellable *cancellable = g_cancellable_new (); + g_object_set_data_full (G_OBJECT (msg), "request-cancellable", + cancellable, g_object_unref); + soup_session_send_and_read_async (info->session, msg, G_PRIORITY_DEFAULT, + cancellable, callback, info); + g_object_unref (msg); +} +#else +void +_gweather_info_queue_request (GWeatherInfo *info, + SoupMessage *msg, + SoupSessionCallback callback) +{ + soup_session_queue_message (info->session, msg, callback, info); +} +#endif + /* it's OK to pass in NULL */ void free_forecast_list (GWeatherInfo *info) @@ -623,7 +646,7 @@ ref_session (GWeatherInfo *info) LIBGWEATHER_VERSION, info->application_id, info->contact_info); - g_object_set (G_OBJECT (session), SOUP_SESSION_USER_AGENT, user_agent, NULL); + g_object_set (G_OBJECT (session), "user-agent", user_agent, NULL); cache = get_cache (); if (cache != NULL) { @@ -734,7 +757,11 @@ gweather_info_abort (GWeatherInfo *info) info->requests_pending = &dummy; for (iter = list; iter; iter = iter->next) - soup_session_cancel_message (info->session, iter->data, SOUP_STATUS_CANCELLED); +#if SOUP_CHECK_VERSION (2, 99, 2) + g_cancellable_cancel (g_object_get_data (iter->data, "request-cancellable")); +#else + soup_session_cancel_message (info->session, iter->data, SOUP_STATUS_CANCELLED); +#endif g_slist_free (list); info->requests_pending = NULL; diff --git a/libgweather/meson.build b/libgweather/meson.build index a2cd84a..2fd6f3b 100644 --- a/libgweather/meson.build +++ b/libgweather/meson.build @@ -97,7 +97,7 @@ configure_file( deps_libgweather = [ dependency('gio-2.0', version: glib_req_version), dependency('gdk-pixbuf-2.0'), - dependency('libsoup-2.4', version: libsoup_req_version), + libsoup_dep, dependency('libxml-2.0', version: libxml_req_version), dependency('geocode-glib-1.0'), diff --git a/libgweather/tests/test_libgweather.c b/libgweather/tests/test_libgweather.c index 1cc8a49..9d6d6a7 100644 --- a/libgweather/tests/test_libgweather.c +++ b/libgweather/tests/test_libgweather.c @@ -414,24 +414,44 @@ test_metar_weather_stations (void) SoupSession *session; GHashTable *stations_ht; char *contents; +#if SOUP_CHECK_VERSION (2, 99, 2) + GBytes *body; + GError *error = NULL; + gsize bsize; +#endif world = gweather_location_get_world (); g_assert_nonnull (world); msg = soup_message_new ("GET", METAR_SOURCES); session = soup_session_new (); +#if SOUP_CHECK_VERSION (2, 99, 2) + body = soup_session_send_and_read (session, msg, NULL, &error); + if (error && error->domain == G_TLS_ERROR) +#else soup_session_send_message (session, msg); - if (msg->status_code == SOUP_STATUS_SSL_FAILED) { + if (msg->status_code == SOUP_STATUS_SSL_FAILED) +#endif + { g_test_message ("SSL/TLS failure, please check your glib-networking installation"); g_test_failed (); return; } +#if SOUP_CHECK_VERSION (2, 99, 2) + g_assert_null (error); + g_assert_cmpint (soup_message_get_status (msg), >=, 200); + g_assert_cmpint (soup_message_get_status (msg), <, 300); + g_assert_nonnull (body); + contents = g_bytes_unref_to_data (body, &bsize); + contents = g_strndup (contents, bsize); + g_bytes_unref (body); +#else g_assert_cmpint (msg->status_code, >=, 200); g_assert_cmpint (msg->status_code, <, 300); - g_object_unref (session); g_assert_nonnull (msg->response_body); - contents = g_strndup (msg->response_body->data, msg->response_body->length); +#endif + g_object_unref (session); g_object_unref (msg); stations_ht = parse_metar_stations (contents); diff --git a/libgweather/weather-iwin.c b/libgweather/weather-iwin.c index d7de12c..170c8b6 100644 --- a/libgweather/weather-iwin.c +++ b/libgweather/weather-iwin.c @@ -296,6 +296,52 @@ parseForecastXml (const char *buff, GWeatherInfo *original_info) return res; } +#if SOUP_CHECK_VERSION (2, 99, 2) +static void +iwin_finish (GObject *source, GAsyncResult *result, gpointer data) +{ + GWeatherInfo *info; + WeatherLocation *loc; + SoupSession *session = SOUP_SESSION (source); + SoupMessage *msg = soup_session_get_async_result_message (session, result); + GBytes *body; + GError *error = NULL; + const char *content; + + body = soup_session_send_and_read_finish (session, result, &error); + + if (!body) { + /* forecast data is not really interesting anyway ;) */ + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_debug ("Failed to get IWIN forecast data: %s\n", error->message); + return; + } + g_warning ("Failed to get IWIN forecast data: %s\n", error->message); + g_clear_error (&error); + _gweather_info_request_done (data, msg); + return; + } else if (!SOUP_STATUS_IS_SUCCESSFUL (soup_message_get_status (msg))) { + g_bytes_unref (body); + g_warning ("Failed to get IWIN forecast data: %d %s\n", + soup_message_get_status (msg), + soup_message_get_reason_phrase (msg)); + _gweather_info_request_done (data, msg); + return; + } + + info = data; + loc = &info->location; + content = g_bytes_get_data (body, NULL); + + g_debug ("iwin data for %s", loc->zone); + g_debug ("%s", content); + + info->forecast_list = parseForecastXml (content, info); + g_bytes_unref (body); + + _gweather_info_request_done (info, msg); +} +#else static void iwin_finish (SoupSession *session, SoupMessage *msg, gpointer data) { @@ -325,6 +371,7 @@ iwin_finish (SoupSession *session, SoupMessage *msg, gpointer data) _gweather_info_request_done (info, msg); } +#endif /* Get forecast into newly alloc'ed string */ gboolean @@ -365,7 +412,7 @@ iwin_start_open (GWeatherInfo *info) g_debug ("iwin_start_open, requesting: %s", url); msg = soup_message_new ("GET", url); _gweather_info_begin_request (info, msg); - soup_session_queue_message (info->session, msg, iwin_finish, info); + _gweather_info_queue_request (info, msg, iwin_finish); g_free (url); diff --git a/libgweather/weather-metar.c b/libgweather/weather-metar.c index 7f3bf46..5b4a1e5 100644 --- a/libgweather/weather-metar.c +++ b/libgweather/weather-metar.c @@ -543,15 +543,46 @@ metar_parse (gchar *metar, GWeatherInfo *info) return TRUE; } +#if SOUP_CHECK_VERSION (2, 99, 2) +static void +metar_finish (GObject *source, GAsyncResult *result, gpointer data) +#else static void metar_finish (SoupSession *session, SoupMessage *msg, gpointer data) +#endif { +#if SOUP_CHECK_VERSION (2, 99, 2) + SoupSession *session = SOUP_SESSION (source); + SoupMessage *msg = soup_session_get_async_result_message (session, result); + GError *error = NULL; + GBytes *body; +#endif GWeatherInfo *info; WeatherLocation *loc; - const gchar *p, *eoln; + const gchar *p, *eoln, *response_body; gchar *searchkey, *metar; gboolean success = FALSE; + info = data; + +#if SOUP_CHECK_VERSION (2, 99, 2) + body = soup_session_send_and_read_finish (session, result, &error); + if (!body) { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_debug ("Failed to get METAR data: %s.\n", error->message); + return; + } + g_warning ("Failed to get METAR data: %s.\n", error->message); + _gweather_info_request_done (info, msg); + return; + } else if (!SOUP_STATUS_IS_SUCCESSFUL (soup_message_get_status (msg))) { + g_bytes_unref (body); + info->network_error = TRUE; + _gweather_info_request_done (info, msg); + return; + } + response_body = g_bytes_get_data (body, NULL); +#else if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { if (msg->status_code == SOUP_STATUS_CANCELLED) { g_debug ("Failed to get METAR data: %d %s.\n", @@ -559,7 +590,6 @@ metar_finish (SoupSession *session, SoupMessage *msg, gpointer data) return; } - info = data; if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)) { info->network_error = TRUE; } else { @@ -571,15 +601,16 @@ metar_finish (SoupSession *session, SoupMessage *msg, gpointer data) _gweather_info_request_done (info, msg); return; } + response_body = msg->response_body->data; +#endif - info = data; loc = &info->location; g_debug ("METAR data for %s", loc->code); - g_debug ("%s", msg->response_body->data); + g_debug ("%s", response_body); searchkey = g_strdup_printf ("<raw_text>%s ", loc->code); - p = strstr (msg->response_body->data, searchkey); + p = strstr (response_body, searchkey); if (p) { p += strlen (searchkey); @@ -594,7 +625,7 @@ metar_finish (SoupSession *session, SoupMessage *msg, gpointer data) g_debug ("Successfully parsed METAR for %s", loc->code); else g_debug ("Failed to parse raw_text METAR for %s", loc->code); - } else if (!strstr (msg->response_body->data, "aviationweather.gov")) { + } else if (!strstr (response_body, "aviationweather.gov")) { /* The response doesn't even seem to have come from NOAA... * most likely it is a wifi hotspot login page. Call that a * network error. @@ -609,6 +640,10 @@ metar_finish (SoupSession *session, SoupMessage *msg, gpointer data) if (!info->valid) info->valid = success; + +#if SOUP_CHECK_VERSION (2, 99, 2) + g_bytes_unref (body); +#endif _gweather_info_request_done (info, msg); } @@ -618,6 +653,12 @@ metar_start_open (GWeatherInfo *info) { WeatherLocation *loc; SoupMessage *msg; +#if SOUP_CHECK_VERSION (2, 99, 2) + GUri *uri; +#else + SoupURI *uri; +#endif + char *query; g_return_if_fail (info != NULL); @@ -628,16 +669,29 @@ metar_start_open (GWeatherInfo *info) return; g_debug ("metar_start_open, requesting: https://www.aviationweather.gov/adds/dataserver_current/httpparam?dataSource=metars&requestType=retrieve&format=xml&hoursBeforeNow=3&mostRecent=true&fields=raw_text&stationString=%s", loc->code); - msg = soup_form_request_new ( - "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam", - "dataSource", "metars", - "requestType", "retrieve", - "format", "xml", - "hoursBeforeNow", "3", - "mostRecent", "true", - "fields", "raw_text", - "stationString", loc->code, - NULL); + query = soup_form_encode ( + "dataSource", "metars", + "requestType", "retrieve", + "format", "xml", + "hoursBeforeNow", "3", + "mostRecent", "true", + "fields", "raw_text", + "stationString", loc->code, + NULL + ); +#if SOUP_CHECK_VERSION (2, 99, 2) + uri = g_uri_build (SOUP_HTTP_URI_FLAGS, + "https", NULL, + "www.aviationweather.gov", -1, + "/adds/dataserver_current/httpparam", + query, + NULL); + g_free (query); +#else + uri = soup_uri_new ("https://www.aviationweather.gov/adds/dataserver_current/httpparam"); + uri->query = query; +#endif + msg = soup_message_new_from_uri ("GET", uri); _gweather_info_begin_request (info, msg); - soup_session_queue_message (info->session, msg, metar_finish, info); + _gweather_info_queue_request (info, msg, metar_finish); } diff --git a/libgweather/weather-metno.c b/libgweather/weather-metno.c index d5b09bd..bf61a23 100644 --- a/libgweather/weather-metno.c +++ b/libgweather/weather-metno.c @@ -290,15 +290,15 @@ fill_info_from_node (GWeatherInfo *info, } static void -parse_forecast_xml_new (GWeatherInfo *original_info, - SoupMessageBody *body) +parse_forecast_xml_new (GWeatherInfo *original_info, + const char *data, gsize length) { xmlDocPtr doc; xmlXPathContextPtr xpath_ctx; xmlXPathObjectPtr xpath_result; int i; - doc = xmlParseMemory (body->data, body->length); + doc = xmlParseMemory (data, length); if (!doc) return; @@ -373,6 +373,57 @@ parse_forecast_xml_new (GWeatherInfo *original_info, xmlFreeDoc (doc); } +#if SOUP_CHECK_VERSION (2, 99, 2) +static void +metno_finish_new (GObject *source, GAsyncResult *result, gpointer data) +{ + GWeatherInfo *info; + WeatherLocation *loc; + SoupSession *session = SOUP_SESSION (source); + SoupMessage *msg = soup_session_get_async_result_message (session, result); + GBytes *body; + GError *error = NULL; + guint num_forecasts; + const char *content; + gsize body_size; + + body = soup_session_send_and_read_finish (session, result, &error); + + if (!body) { + /* forecast data is not really interesting anyway ;) */ + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_debug ("Failed to get met.no forecast data: %s\n", error->message); + return; + } + g_message ("Failed to get met.no forecast data: %s\n", error->message); + g_clear_error (&error); + _gweather_info_request_done (data, msg); + return; + } else if (!SOUP_STATUS_IS_SUCCESSFUL (soup_message_get_status (msg))) { + g_message ("Failed to get met.no forecast data: %d %s\n", + soup_message_get_status (msg), + soup_message_get_reason_phrase (msg)); + _gweather_info_request_done (data, msg); + return; + } + + content = g_bytes_get_data (body, &body_size); + + info = data; + loc = &info->location; + g_debug ("metno data for %lf, %lf", loc->latitude, loc->longitude); + g_debug ("%s", content); + + parse_forecast_xml_new (info, content, body_size); + num_forecasts = g_slist_length (info->forecast_list); + g_debug ("metno parsed %d forecast infos", num_forecasts); + if (!info->valid) + info->valid = (num_forecasts > 0); + + g_bytes_unref (body); + _gweather_info_request_done (info, msg); +} +#else static void metno_finish_new (SoupSession *session, SoupMessage *msg, @@ -400,7 +451,8 @@ metno_finish_new (SoupSession *session, g_debug ("metno data for %lf, %lf", loc->latitude, loc->longitude); g_debug ("%s", msg->response_body->data); - parse_forecast_xml_new (info, msg->response_body); + parse_forecast_xml_new (info, msg->response_body->data, + msg->response_body->length); num_forecasts = g_slist_length (info->forecast_list); g_debug ("metno parsed %d forecast infos", num_forecasts); if (!info->valid) @@ -408,6 +460,7 @@ metno_finish_new (SoupSession *session, _gweather_info_request_done (info, msg); } +#endif gboolean metno_start_open (GWeatherInfo *info) @@ -433,7 +486,7 @@ metno_start_open (GWeatherInfo *info) message = soup_message_new ("GET", url); _gweather_info_begin_request (info, message); - soup_session_queue_message (info->session, message, metno_finish_new, info); + _gweather_info_queue_request (info, message, metno_finish_new); g_free (url); diff --git a/libgweather/weather-owm.c b/libgweather/weather-owm.c index 2976be1..0bdc7bd 100644 --- a/libgweather/weather-owm.c +++ b/libgweather/weather-owm.c @@ -345,15 +345,15 @@ make_info_from_node (GWeatherInfo *original_info, } static void -parse_forecast_xml (GWeatherInfo *original_info, - SoupMessageBody *body) +parse_forecast_xml (GWeatherInfo *original_info, + const char *data, gsize length) { xmlDocPtr doc; xmlXPathContextPtr xpath_ctx; xmlXPathObjectPtr xpath_result; int i; - doc = xmlParseMemory (body->data, body->length); + doc = xmlParseMemory (data, length); if (!doc) return; @@ -388,6 +388,54 @@ parse_forecast_xml (GWeatherInfo *original_info, xmlFreeDoc (doc); } +#if SOUP_CHECK_VERSION (2, 99, 2) +static void +owm_finish (GObject *source, GAsyncResult *result, gpointer data) +{ + GWeatherInfo *info; + WeatherLocation *loc; + SoupSession *session = SOUP_SESSION (source); + SoupMessage *msg = soup_session_get_async_result_message (session, result); + GBytes *body; + GError *error = NULL; + const char *content; + gsize length; + + body = soup_session_send_and_read_finish (session, result, &error); + + if (!body) { + /* forecast data is not really interesting anyway ;) */ + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_debug ("Failed to get OpenWeatheRMap forecast data: %s\n", + error->message); + return; + } + g_warning ("Failed to get OpenWeatherMap forecast data: %s\n", + error->message); + g_clear_error (&error); + _gweather_info_request_done (data, msg); + return; + } else if (!SOUP_STATUS_IS_SUCCESSFUL (soup_message_get_status (msg))) { + g_bytes_unref (body); + g_warning ("Failed to get OpenWeatherMap forecast data: %d %s\n", + soup_message_get_status (msg), + soup_message_get_reason_phrase (msg)); + _gweather_info_request_done (data, msg); + return; + } + + content = g_bytes_get_data (body, &length); + + info = data; + loc = &info->location; + g_debug ("owm data for %lf, %lf", loc->latitude, loc->longitude); + g_debug ("%s", content); + + parse_forecast_xml (info, content, length); + g_bytes_unref (body); + _gweather_info_request_done (info, msg); +} +#else static void owm_finish (SoupSession *session, SoupMessage *msg, @@ -414,9 +462,11 @@ owm_finish (SoupSession *session, g_debug ("owm data for %lf, %lf", loc->latitude, loc->longitude); g_debug ("%s", msg->response_body->data); - parse_forecast_xml (info, msg->response_body); + parse_forecast_xml (info, msg->response_body->data, + msg->response_body->length); _gweather_info_request_done (info, msg); } +#endif gboolean owm_start_open (GWeatherInfo *info) @@ -451,7 +501,7 @@ owm_start_open (GWeatherInfo *info) message = soup_message_new ("GET", url); _gweather_info_begin_request (info, message); - soup_session_queue_message (info->session, message, owm_finish, info); + _gweather_info_queue_request (info, message, owm_finish); g_free (url); diff --git a/meson.build b/meson.build index bef96ac..c27dd60 100644 --- a/meson.build +++ b/meson.build @@ -31,11 +31,29 @@ pkgdatadir = datadir / 'libgweather-4' pkglibdir = libdir / 'libgweather-4' glib_req_version = '>= 2.44.0' -libsoup_req_version = '>= 2.44.0' libxml_req_version = '>= 2.6.0' GETTEXT_PACKAGE = libgweather_full_version LOCATIONS_GETTEXT_PACKAGE = libgweather_full_version + '-locations' +gtk_req_version = '>= 3.13.5' +libxml_req_version = '>= 2.6.0' + +if get_option('soup2') + libsoup_name = 'libsoup-2.4' + libsoup_req_version = '>= 2.44.0' +else + libsoup_name = 'libsoup-3.0' + libsoup_req_version = '>= 2.99.2' +endif + +c_compiler = meson.get_compiler('c') +gtk_dep = dependency('gtk+-3.0', version: gtk_req_version) +glib_dep = dependency('gio-2.0', version: glib_req_version) +libsoup_dep = dependency(libsoup_name, version: libsoup_req_version) +libxml_dep = dependency('libxml-2.0', version: libxml_req_version) +geocode_glib_dep = dependency('geocode-glib-1.0') +math_dep = c_compiler.find_library('m', required : false) +deps_libgweather = [math_dep, gtk_dep, glib_dep, libsoup_dep, libxml_dep, geocode_glib_dep] pylint = find_program('pylint-3', 'pylint3', 'pylint', required: false) pylint_flags = [ diff --git a/meson_options.txt b/meson_options.txt index 0e354da..7988a6b 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -8,3 +8,5 @@ option('gtk_doc', type: 'boolean', value: true, description: 'Whether to generate the API reference') option('introspection', type: 'boolean', value: true, description: 'Whether to generate introspection data') +option('soup2', type: 'boolean', value: true, + description: 'Whether to build with libsoup2') |