diff --git a/.gitignore b/.gitignore index 8e4626c..6020300 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ /geoclue-2.5.7.tar.bz2 /geoclue-2.6.0.tar.bz2 /geoclue-2.7.0.tar.bz2 +/geoclue-2.7.2.tar.bz2 diff --git a/0001-remove-mozilla-location-service.patch b/0001-remove-mozilla-location-service.patch deleted file mode 100644 index 4b8daec..0000000 --- a/0001-remove-mozilla-location-service.patch +++ /dev/null @@ -1,390 +0,0 @@ -From 6e278e5df52a536ba868c6f193f003ddb98254cc Mon Sep 17 00:00:00 2001 -From: Teemu Ikonen -Date: Wed, 19 Jun 2024 12:26:15 +0300 -Subject: [PATCH 1/7] config: Remove DEFAULT_WIFI_URL and - DEFAULT_WIFI_SUBMIT_URL - -If wifi URL is not set in config, disable wifi, 3g and cdma sources. - -If wifi submission URL is not set in config, disable wifi submissions, -i.e. set wifi/submit-data to false. - -Warn about missing WiFi locate and submit URLs only if the source or -submission is enabled. ---- - src/gclue-config.c | 24 ++++++++++++------------ - 1 file changed, 12 insertions(+), 12 deletions(-) - -diff --git a/src/gclue-config.c b/src/gclue-config.c -index e04d6089..c6e89195 100644 ---- a/src/gclue-config.c -+++ b/src/gclue-config.c -@@ -265,8 +265,6 @@ load_enable_source_config (GClueConfig *config, - return enable; - } - --#define DEFAULT_WIFI_URL "https://location.services.mozilla.com/v1/geolocate?key=" MOZILLA_API_KEY --#define DEFAULT_WIFI_SUBMIT_URL "https://location.services.mozilla.com/v2/geosubmit?key=" MOZILLA_API_KEY - #define DEFAULT_WIFI_SUBMIT_NICK "geoclue" - - static void -@@ -291,11 +289,7 @@ load_wifi_config (GClueConfig *config, gboolean initial) - if (error == NULL) { - g_clear_pointer (&priv->wifi_url, g_free); - priv->wifi_url = g_steal_pointer (&wifi_url); -- } else if (initial) { -- g_debug ("Using the default locate URL: %s", error->message); -- g_clear_pointer (&priv->wifi_url, g_free); -- priv->wifi_url = g_strdup (DEFAULT_WIFI_URL); -- } else -+ } else if (priv->enable_wifi_source) - g_warning ("Failed to get config \"wifi/url\": %s", error->message); - - g_clear_error (&error); -@@ -323,11 +317,7 @@ load_wifi_config (GClueConfig *config, gboolean initial) - if (error == NULL) { - g_clear_pointer (&priv->wifi_submit_url, g_free); - priv->wifi_submit_url = g_steal_pointer (&wifi_submit_url); -- } else if (initial) { -- g_debug ("Using the default submission URL: %s", error->message); -- g_clear_pointer (&priv->wifi_submit_url, g_free); -- priv->wifi_submit_url = g_strdup (DEFAULT_WIFI_SUBMIT_URL); -- } else -+ } else if (priv->wifi_submit) - g_warning ("Failed to get config \"wifi/submission-url\": %s", error->message); - - g_clear_error (&error); -@@ -595,6 +585,16 @@ gclue_config_init (GClueConfig *config) - load_config_file (config, path, FALSE); - } - out: -+ if (!config->priv->wifi_url -+ && (config->priv->enable_wifi_source || config->priv->enable_3g_source)) { -+ g_warning ("Wifi URL is not set, disabling wifi and 3g sources"); -+ config->priv->enable_wifi_source = FALSE; -+ config->priv->enable_3g_source = FALSE; -+ } -+ if (!config->priv->wifi_submit_url && config->priv->wifi_submit) { -+ g_warning ("Wifi submit URL is not set, disabling wifi submissions"); -+ config->priv->wifi_submit = FALSE; -+ } - gclue_config_print (config); - } - --- -GitLab - - -From a9edf0bebf696e49f57fe412227b91371f42a949 Mon Sep 17 00:00:00 2001 -From: Teemu Ikonen -Date: Wed, 19 Jun 2024 15:34:55 +0300 -Subject: [PATCH 2/7] config: Improve gclue_config_print() output - -Indent the sub-configuration of sources. - -Precede agent whitelist with 'Allowed agents:' instead of 'Agents:'. ---- - src/gclue-config.c | 14 +++++++------- - 1 file changed, 7 insertions(+), 7 deletions(-) - -diff --git a/src/gclue-config.c b/src/gclue-config.c -index c6e89195..921ef6e7 100644 ---- a/src/gclue-config.c -+++ b/src/gclue-config.c -@@ -490,14 +490,14 @@ gclue_config_print (GClueConfig *config) - - g_debug ("GeoClue configuration:"); - if (config->priv->num_agents > 0) { -- g_debug ("Agents:"); -+ g_debug ("Allowed agents:"); - for (i = 0; i < config->priv->num_agents; i++) - g_debug ("\t%s", config->priv->agents[i]); - } else -- g_debug ("Agents: none"); -+ g_debug ("Allowed agents: none"); - g_debug ("Network NMEA source: %s", - config->priv->enable_nmea_source? "enabled": "disabled"); -- g_debug ("Network NMEA socket: %s", -+ g_debug ("\tNetwork NMEA socket: %s", - config->priv->nmea_socket == NULL? "none": config->priv->nmea_socket); - g_debug ("3G source: %s", - config->priv->enable_3g_source? "enabled": "disabled"); -@@ -508,14 +508,14 @@ gclue_config_print (GClueConfig *config) - g_debug ("WiFi source: %s", - config->priv->enable_wifi_source? "enabled": "disabled"); - redacted_locate_url = redact_api_key (config->priv->wifi_url); -- g_debug ("WiFi locate URL: %s", -+ g_debug ("\tWiFi locate URL: %s", - redacted_locate_url == NULL ? "none" : redacted_locate_url); - redacted_submit_url = redact_api_key (config->priv->wifi_submit_url); -- g_debug ("WiFi submit URL: %s", -+ g_debug ("\tWiFi submit URL: %s", - redacted_submit_url == NULL ? "none" : redacted_submit_url); -- g_debug ("WiFi submit data: %s", -+ g_debug ("\tWiFi submit data: %s", - config->priv->wifi_submit? "enabled": "disabled"); -- g_debug ("WiFi submission nickname: %s", -+ g_debug ("\tWiFi submission nickname: %s", - config->priv->wifi_submit_nick == NULL? "none": config->priv->wifi_submit_nick); - g_debug ("Static source: %s", - config->priv->enable_static_source? "enabled": "disabled"); --- -GitLab - - -From 68dd2f75697b330c9b2c80ddebd3b92b3054f143 Mon Sep 17 00:00:00 2001 -From: Teemu Ikonen -Date: Wed, 19 Jun 2024 12:30:21 +0300 -Subject: [PATCH 3/7] meson: Remove mozilla-api-key option - -The wifi API key can be set directly in the wifi/url config key. ---- - meson.build | 1 - - meson_options.txt | 3 --- - 2 files changed, 4 deletions(-) - -diff --git a/meson.build b/meson.build -index b175096a..086879fa 100644 ---- a/meson.build -+++ b/meson.build -@@ -30,7 +30,6 @@ conf.set_quoted('PACKAGE_BUGREPORT', 'https://gitlab.freedesktop.org/geoclue/geo - conf.set_quoted('TEST_SRCDIR', meson.project_source_root() + '/data/') - conf.set_quoted('LOCALEDIR', localedir) - conf.set_quoted('SYSCONFDIR', sysconfdir) --conf.set_quoted('MOZILLA_API_KEY', get_option('mozilla-api-key')) - conf.set10('GCLUE_USE_3G_SOURCE', get_option('3g-source')) - conf.set10('GCLUE_USE_CDMA_SOURCE', get_option('cdma-source')) - conf.set10('GCLUE_USE_MODEM_GPS_SOURCE', get_option('modem-gps-source')) -diff --git a/meson_options.txt b/meson_options.txt -index 5b8c42d2..946d7ead 100644 ---- a/meson_options.txt -+++ b/meson_options.txt -@@ -40,6 +40,3 @@ option('systemd-system-unit-dir', - option('dbus-srv-user', - type: 'string', value: 'root', - description: 'The user (existing) as which the service will run') --option('mozilla-api-key', -- type: 'string', value: 'geoclue', -- description: 'Your API key for Mozilla Location Service') --- -GitLab - - -From d8a344d3aa1989ab1888fc5fac7a46964c6082e4 Mon Sep 17 00:00:00 2001 -From: Teemu Ikonen -Date: Wed, 19 Jun 2024 15:03:53 +0300 -Subject: [PATCH 4/7] README: Remove trailing whitespace - ---- - README.md | 36 ++++++++++++++++++------------------ - 1 file changed, 18 insertions(+), 18 deletions(-) - -diff --git a/README.md b/README.md -index b4831575..5bad1ed7 100644 ---- a/README.md -+++ b/README.md -@@ -25,49 +25,49 @@ your phone. For using phone GPS, you'll need to install the latest version of - [GeoclueShare app](https://github.com/ankitstarski/GeoclueShare/releases) - on your phone (currently, this is supported only on Android devices). - --Geoclue was also used for (reverse-)geocoding but that functionality has --been dropped in favour of the -+Geoclue was also used for (reverse-)geocoding but that functionality has -+been dropped in favour of the - [geocode-glib library](http://ftp.gnome.org/pub/GNOME/sources/geocode-glib/). - - # History --Geoclue was started during the GNOME Summit 2006 in Boston. At least --Keith Preston and Tuomas Kuosmanen can be blamed. There was a total rewrite -+Geoclue was started during the GNOME Summit 2006 in Boston. At least -+Keith Preston and Tuomas Kuosmanen can be blamed. There was a total rewrite - after version 0.9. - --There was yet another rewrite that we call geoclue2. The first version to -+There was yet another rewrite that we call geoclue2. The first version to - introduce the re-write was version 1.99. - - # Communication and Contribution - --- Discussions take place on the -+- Discussions take place on the - [GNOME Discourse](https://discourse.gnome.org/c/platform). - - The IRC chat for geoclue is on __#gnome-maps__ at irc.gimp.org . --- Issues are tracked on -+- Issues are tracked on - [Gitlab](https://gitlab.freedesktop.org/geoclue/geoclue/issues). - - # Get Source Code - The source code is available as a tar-ball and in a Git repository. - --For latest release tarballs, use the `Download` option of Gitlab on the -+For latest release tarballs, use the `Download` option of Gitlab on the - [tag of your choice](https://gitlab.freedesktop.org/geoclue/geoclue/tags/). - --Older (than 2.4.13) releases are available -+Older (than 2.4.13) releases are available - [here](http://www.freedesktop.org/software/geoclue/releases/2.4/). - - Git repository for Geoclue: https://gitlab.freedesktop.org/geoclue/geoclue -- -+ - # Building Geoclue - --The guidelines for building geoclue have been documented --[here](https://gitlab.freedesktop.org/geoclue/geoclue/blob/master/HACKING.md). -+The guidelines for building geoclue have been documented -+[here](https://gitlab.freedesktop.org/geoclue/geoclue/blob/master/HACKING.md). - - # Using Geoclue in an application -- --- __D-Bus API__: The documentation for using geoclue with D-Bus API is -+ -+- __D-Bus API__: The documentation for using geoclue with D-Bus API is - [here](http://www.freedesktop.org/software/geoclue/docs/). --- __Libgeoclue API documentation__: The documentation is available -+- __Libgeoclue API documentation__: The documentation is available - [here](https://www.freedesktop.org/software/geoclue/docs/libgeoclue/). --- __C user application__: -+- __C user application__: - [Here](https://gitlab.freedesktop.org/geoclue/geoclue/blob/master/demo/where-am-i.c) --is an example showing a C application that uses --geoclue to locate its user. -+is an example showing a C application that uses -+geoclue to locate its user. --- -GitLab - - -From 7388e4ef1489b0cdf9c8d83c331ce0c3f6aa76b9 Mon Sep 17 00:00:00 2001 -From: Teemu Ikonen -Date: Wed, 19 Jun 2024 15:03:23 +0300 -Subject: [PATCH 5/7] README: Add information about MLS retirement - ---- - README.md | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/README.md b/README.md -index 5bad1ed7..1d638770 100644 ---- a/README.md -+++ b/README.md -@@ -15,13 +15,13 @@ Geoclue comprises the following functionalities : - - GeoIP (accuracy: city-level) - - Static location source (reads location from a system-wide file) - --WiFi-based geolocation makes use of --[Mozilla Location Service](https://wiki.mozilla.org/CloudServices/Location). -+WiFi and cell tower-based geolocation used to use -+[Mozilla Location Service](https://wiki.mozilla.org/CloudServices/Location), -+which closed on June 12th, 2024. Geoclue currently does not enable WiFi location -+by default, but various commercial services offering a similar location API -+exist. - --If geoclue is unable to find you, you can easily fix that by installing --and running a --[simple app](https://wiki.mozilla.org/CloudServices/Location#Contributing) on --your phone. For using phone GPS, you'll need to install the latest version of -+For using phone GPS, you can install the latest version of - [GeoclueShare app](https://github.com/ankitstarski/GeoclueShare/releases) - on your phone (currently, this is supported only on Android devices). - --- -GitLab - - -From e78e475a68e7ea4f6b7cf5a1d84bff9d1ec8f588 Mon Sep 17 00:00:00 2001 -From: Teemu Ikonen -Date: Wed, 19 Jun 2024 15:05:34 +0300 -Subject: [PATCH 6/7] data: geoclue.conf.in: Remove Mozilla URLs - ---- - data/geoclue.conf.in | 21 ++++++++++----------- - 1 file changed, 10 insertions(+), 11 deletions(-) - -diff --git a/data/geoclue.conf.in b/data/geoclue.conf.in -index 9afb5e08..62ba28ce 100644 ---- a/data/geoclue.conf.in -+++ b/data/geoclue.conf.in -@@ -47,12 +47,12 @@ enable=true - # source will be used instead. - enable=true - --# URL to the WiFi geolocation service. If not set, defaults to Mozilla's --# Location Service with a hardcoded key. To use a custom key, uncomment this URL --# while changing YOUR_KEY to your MLS API key. --#url=https://location.services.mozilla.com/v1/geolocate?key=YOUR_KEY -+# URL to a WiFi geolocation service compatible with the Ichnaea API -+# (https://ichnaea.readthedocs.io/en/latest/api/geolocate.html). -+# An API key can be set by using the 'key' URL parameter. -+#url=https://example.com/v1/geolocate?key=YOUR_KEY - --# To use the Google geolocation service instead of Mozilla's, uncomment this URL -+# To use the Google geolocation service, uncomment this URL - # while changing YOUR_KEY to your Google API key. - # - # WARNING: Please make sure that you are complying with the Google's ToS and -@@ -62,8 +62,8 @@ enable=true - # - #url=https://www.googleapis.com/geolocation/v1/geolocate?key=YOUR_KEY - --# Submit data to Mozilla Location Service --# If set to true, geoclue will automatically submit network data to Mozilla -+# Submit data to WiFi geolocation service -+# If set to true, geoclue will automatically submit network data - # each time it gets a GPS lock. - # - # Currently, only Modem-GPS or Network NMEA sources are supported as providers -@@ -74,10 +74,9 @@ enable=true - # - submit-data=false - --# URL to submission API of Mozilla Location Service. If not set, defaults to --# Mozilla's API with a hardcoded key. To use a custom key, uncomment this URL --# while changing YOUR_KEY to your MLS API key. --#submission-url=https://location.services.mozilla.com/v2/geosubmit?key=YOUR_KEY -+# URL to submit data to a WiFi geolocation service with an Ichnaea compatible API -+# (https://ichnaea.readthedocs.io/en/latest/api/geosubmit2.html). -+#submission-url=https://example.com/v2/geosubmit?key=YOUR_KEY - - # A nickname to submit network data with. A nickname must be 2-32 characters long. - submission-nick=geoclue --- -GitLab - - -From 4c99cba1c029b9ea1444e529ffae13e1f0a6bd36 Mon Sep 17 00:00:00 2001 -From: Teemu Ikonen -Date: Wed, 19 Jun 2024 15:25:38 +0300 -Subject: [PATCH 7/7] data: geoclue.conf.in: Disable WiFi and 3g sources - -We do not have a replecement for the MLS database, so these sources do -not work. ---- - data/geoclue.conf.in | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/data/geoclue.conf.in b/data/geoclue.conf.in -index 62ba28ce..c6ecd2e2 100644 ---- a/data/geoclue.conf.in -+++ b/data/geoclue.conf.in -@@ -25,7 +25,7 @@ enable=true - [3g] - - # Enable 3G source --enable=true -+enable=false - - # CDMA source configuration options - [cdma] -@@ -45,7 +45,7 @@ enable=true - # Enable WiFi source - # If this source and the static source below are both disabled a GeoIP-only - # source will be used instead. --enable=true -+enable=false - - # URL to a WiFi geolocation service compatible with the Ichnaea API - # (https://ichnaea.readthedocs.io/en/latest/api/geolocate.html). --- -GitLab - diff --git a/geoclue-2.7.2-git41-backports.patch b/geoclue-2.7.2-git41-backports.patch new file mode 100644 index 0000000..2978025 --- /dev/null +++ b/geoclue-2.7.2-git41-backports.patch @@ -0,0 +1,3094 @@ +From 7b8aa789c0a3a4b422e02a5f92b7c9d47a2e75fe Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= +Date: Sat, 19 Oct 2024 17:36:11 +0200 +Subject: [PATCH] data: geoclue.conf.in: Mention the geolocation service + defined at build-time + +The geolocation service to use can also be defined at build time using the +'default-wifi-url' meson option. This service will be used when no url= +parameter is set in the config file, make that a bit more obvious by +mentioning it explicitly in the documentation. +--- + data/geoclue.conf.in | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/data/geoclue.conf.in b/data/geoclue.conf.in +index 0eb59cd..124334c 100644 +--- a/data/geoclue.conf.in ++++ b/data/geoclue.conf.in +@@ -50,6 +50,7 @@ enable=@default_wifi_enable@ + # URL to a WiFi geolocation service compatible with the Ichnaea API + # (https://ichnaea.readthedocs.io/en/latest/api/geolocate.html). + # An API key can be set by using the 'key' URL parameter. ++# If unset, defaults to a location service defined at build-time. + #url=https://example.com/v1/geolocate?key=YOUR_KEY + + # To use the Google geolocation service, uncomment this URL +-- +2.48.1 + + +From 3422928dd1d11bfaee59cffc267286e5b4d550bd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= +Date: Sat, 19 Oct 2024 17:40:40 +0200 +Subject: [PATCH] data: geoclue.conf.in: Add URL and API key for the Positon + location service + +Allow users and distributions to opt into using the Positon +(https://positon.xyz) geolocation service for wifi and cell tower locations. + +The API key that's used here was assigned to geoclue by Positon, and may be +used by non-commercial re-distributors of geoclue as well. + +See also https://gitlab.freedesktop.org/geoclue/geoclue/-/issues/200 +--- + data/geoclue.conf.in | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/data/geoclue.conf.in b/data/geoclue.conf.in +index 124334c..7298353 100644 +--- a/data/geoclue.conf.in ++++ b/data/geoclue.conf.in +@@ -53,6 +53,27 @@ enable=@default_wifi_enable@ + # If unset, defaults to a location service defined at build-time. + #url=https://example.com/v1/geolocate?key=YOUR_KEY + ++# To use the Positon geolocation service, uncomment this URL. ++# ++# NOTE: Distributors of geoclue may only uncomment this URL if the ++# service is used in a non-commercial manner, to quote Positon: ++# ++# We generally consider a service or software commercial, when it is only ++# intended to be available (beyond free trials or other restrictions) via ++# a one-time payment, subscription, account registration or similar. ++# Funding the development through donations or optional support contracts ++# does not make the software itself commercial. ++# ++# Fedora Linux, CentOS Stream, Rocky Linux or AlmaLinux all would not be ++# considered commercial by us, neither would e.g. Debian, Ubuntu or ++# elementary OS. However, RedHat Enterprise Linux and various SUSE Linux ++# Enterprise versions would be considered commercial. ++# ++# For more information, contact Positon or consult their website: ++# https://positon.xyz/docs/ ++# ++#url=https://api.positon.xyz/v1/geolocate?key=56aba903-ae67-4f26-919b-15288b44bda9 ++ + # To use the Google geolocation service, uncomment this URL + # while changing YOUR_KEY to your Google API key. + # +-- +2.48.1 + + +From 7500e385a1a0f0f9985f74870f8504bd9ac77ea1 Mon Sep 17 00:00:00 2001 +From: Chris Talbot +Date: Sun, 1 Dec 2024 21:33:38 -0700 +Subject: [PATCH] Mozilla: Include SSID for geolocate and submission requests + +--- + src/gclue-mozilla.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/src/gclue-mozilla.c b/src/gclue-mozilla.c +index 9e8feb1..abb2280 100644 +--- a/src/gclue-mozilla.c ++++ b/src/gclue-mozilla.c +@@ -257,6 +257,7 @@ gclue_mozilla_create_query (GClueMozilla *mozilla, + for (iter = bss_list; iter != NULL; iter = iter->next) { + WPABSS *bss = WPA_BSS (iter->data); + char mac[BSSID_STR_LEN + 1] = { 0 }; ++ char ssid[MAX_SSID_LEN + 1] = { 0 }; + gint16 strength_dbm; + guint age_ms; + +@@ -269,6 +270,10 @@ gclue_mozilla_create_query (GClueMozilla *mozilla, + get_bssid_from_bss (bss, mac); + json_builder_add_string_value (builder, mac); + ++ json_builder_set_member_name (builder, "ssid"); ++ get_ssid_from_bss (bss, ssid); ++ json_builder_add_string_value (builder, ssid); ++ + json_builder_set_member_name (builder, "signalStrength"); + strength_dbm = wpa_bss_get_signal (bss); + json_builder_add_int_value (builder, strength_dbm); +@@ -486,6 +491,7 @@ gclue_mozilla_create_submit_query (GClueMozilla *mozilla, + for (iter = bss_list; iter != NULL; iter = iter->next) { + WPABSS *bss = WPA_BSS (iter->data); + char mac[BSSID_STR_LEN + 1] = { 0 }; ++ char ssid[MAX_SSID_LEN + 1] = { 0 }; + gint16 strength_dbm; + guint16 frequency; + guint age_ms; +@@ -499,6 +505,10 @@ gclue_mozilla_create_submit_query (GClueMozilla *mozilla, + get_bssid_from_bss (bss, mac); + json_builder_add_string_value (builder, mac); + ++ json_builder_set_member_name (builder, "ssid"); ++ get_ssid_from_bss (bss, ssid); ++ json_builder_add_string_value (builder, ssid); ++ + json_builder_set_member_name (builder, "signalStrength"); + strength_dbm = wpa_bss_get_signal (bss); + json_builder_add_int_value (builder, strength_dbm); +-- +2.48.1 + + +From 87efd9a932cf9b723d6fc84f7b61ebb4cc09d635 Mon Sep 17 00:00:00 2001 +From: Chris Talbot +Date: Sun, 1 Dec 2024 21:34:44 -0700 +Subject: [PATCH] Mozilla: replace rather than append User-Agent + +It won't actually attach if you don't do this +--- + src/gclue-mozilla.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/gclue-mozilla.c b/src/gclue-mozilla.c +index abb2280..2b3467d 100644 +--- a/src/gclue-mozilla.c ++++ b/src/gclue-mozilla.c +@@ -301,7 +301,7 @@ gclue_mozilla_create_query (GClueMozilla *mozilla, + uri = gclue_mozilla_get_locate_url (mozilla); + ret = soup_message_new ("POST", uri); + request_headers = soup_message_get_request_headers (ret); +- soup_message_headers_append (request_headers, "User-Agent", USER_AGENT); ++ soup_message_headers_replace (request_headers, "User-Agent", USER_AGENT); + body = g_bytes_new_take (data, data_len); + soup_message_set_request_body_from_bytes (ret, "application/json", body); + g_debug ("Sending following request to '%s':\n%s", uri, data); +@@ -566,7 +566,7 @@ gclue_mozilla_create_submit_query (GClueMozilla *mozilla, + + ret = soup_message_new ("POST", url); + request_headers = soup_message_get_request_headers (ret); +- soup_message_headers_append (request_headers, "User-Agent", USER_AGENT); ++ soup_message_headers_replace (request_headers, "User-Agent", USER_AGENT); + if (nick != NULL && nick[0] != '\0') + soup_message_headers_append (request_headers, + "X-Nickname", +-- +2.48.1 + + +From 72b1c3794e86ef97ba398a64446a0d84ae1ef2ad Mon Sep 17 00:00:00 2001 +From: sarayourfriend +Date: Wed, 4 Dec 2024 13:56:41 +1100 +Subject: [PATCH] lib: simple: forward xdp location start errors + +Instead of squashing the error as a generic gio failed, +forward the xdp error itself, so that the callsite can +determine the cause of the failure. + +Signed-off-by: Sara Marcondes +--- + libgeoclue/gclue-simple.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/libgeoclue/gclue-simple.c b/libgeoclue/gclue-simple.c +index 4c2f299..7a96baf 100644 +--- a/libgeoclue/gclue-simple.c ++++ b/libgeoclue/gclue-simple.c +@@ -551,10 +551,7 @@ on_portal_started_finish (GObject *source_object, + g_autoptr (GError) error = NULL; + + if (!xdp_location_call_start_finish (priv->portal, NULL, res, &error)) { +- if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) +- g_task_return_error (task, g_steal_pointer (&error)); +- else +- g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "Start failed"); ++ g_task_return_error (task, g_steal_pointer (&error)); + } else { + async_init_return_error_when_cancelled (task); + } +-- +2.48.1 + + +From 596231b53dc71f91355b093946fdd8c98af48f4e Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Tue, 19 Nov 2024 14:15:59 +0200 +Subject: [PATCH] location: Ignore NMEA coordinates without degree digits + +The coordinates for latitude and longitude in NMEA sentences are given +as strings in the format `ddmm.mm` where ds are the digits for degrees +and mm.mm is the float value for minutes. Degree values for latitudes +are between 1 to 2 digits (0 to 90) and between 1 to 3 digits (0 to 180) +for longitudes. Implementations seem to mostly output degrees +zero-padded with 2 digits for latitude and 3 digits with longitude. + +We now reject coordinate strings without at least one character for +degree, so that e.g. "012.3456" is allowed, but "12.3456" is not. + +Previously, coordinate strings without digit values were parsed, leading +to erroneous output. + +Thanks to Benoit Maurin for reporting this. +--- + src/gclue-location.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/gclue-location.c b/src/gclue-location.c +index da2a10a..83f51bd 100644 +--- a/src/gclue-location.c ++++ b/src/gclue-location.c +@@ -449,6 +449,8 @@ parse_coordinate_string (const char *coordinate, + if (dot_str == NULL) + return INVALID_COORDINATE; + dot_offset = dot_str - coordinate; ++ if (dot_offset < 3) ++ return INVALID_COORDINATE; + + degrees_str = g_strndup (coordinate, dot_offset - 2); + degrees = g_ascii_strtod (degrees_str, NULL); +-- +2.48.1 + + +From 3baf0c7442adfcd195bcd1f08b8d8ae8f8a79894 Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Tue, 19 Nov 2024 17:30:07 +0200 +Subject: [PATCH] location: Stricter NMEA coordinate string parsing + +Add check for NULL coordinate and direction strings, remove duplicate +check for empty direction string. + +Check coordinate string for chars which are not a digit or '.' and +reject such strings. + +Check that the full minutes part of the string is consumed by +g_ascii_strtod(), reject the string if not. The degrees part is covered +by other checks on the coordinate string. +--- + src/gclue-location.c | 27 +++++++++++++++++++-------- + 1 file changed, 19 insertions(+), 8 deletions(-) + +diff --git a/src/gclue-location.c b/src/gclue-location.c +index 83f51bd..eb6d66f 100644 +--- a/src/gclue-location.c ++++ b/src/gclue-location.c +@@ -428,12 +428,11 @@ parse_coordinate_string (const char *coordinate, + { + gdouble minutes, degrees, out; + g_autofree gchar *degrees_str = NULL; +- gchar *dot_str; ++ const char *c, *dot_str, *coordinate_end; ++ char *conversion_end; + gint dot_offset; + +- if (coordinate[0] == '\0' || +- direction[0] == '\0' || +- direction[0] == '\0') ++ if (!coordinate || !direction || coordinate[0] == '\0' || direction[0] == '\0') + return INVALID_COORDINATE; + + if (direction[0] != 'N' && +@@ -445,17 +444,29 @@ parse_coordinate_string (const char *coordinate, + return INVALID_COORDINATE; + } + ++ for (c = coordinate; *c != '\0'; c++) { ++ if (!(g_ascii_isdigit (*c) || *c == '.')) { ++ g_warning ("Invalid coordinate string '%s'", coordinate); ++ return INVALID_COORDINATE; ++ } ++ } ++ coordinate_end = c; ++ + dot_str = g_strstr_len (coordinate, 6, "."); +- if (dot_str == NULL) +- return INVALID_COORDINATE; + dot_offset = dot_str - coordinate; +- if (dot_offset < 3) ++ if (!dot_str || dot_offset < 3) { ++ g_warning ("Invalid coordinate string '%s'", coordinate); + return INVALID_COORDINATE; ++ } + + degrees_str = g_strndup (coordinate, dot_offset - 2); + degrees = g_ascii_strtod (degrees_str, NULL); + +- minutes = g_ascii_strtod (dot_str - 2, NULL); ++ minutes = g_ascii_strtod (dot_str - 2, &conversion_end); ++ if (conversion_end != coordinate_end) { ++ g_warning ("Invalid coordinate string '%s'", coordinate); ++ return INVALID_COORDINATE; ++ } + + /* Include the minutes as part of the degrees */ + out = degrees + (minutes / 60.0); +-- +2.48.1 + + +From 52d383c8634c6601c811fbd3b8ac75d48c0b4765 Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Sun, 8 Dec 2024 19:50:09 +0200 +Subject: [PATCH] location: Check parsed NMEA coordinates for correct range + +--- + src/gclue-location.c | 22 +++++++++++++++++----- + 1 file changed, 17 insertions(+), 5 deletions(-) + +diff --git a/src/gclue-location.c b/src/gclue-location.c +index eb6d66f..b4747ad 100644 +--- a/src/gclue-location.c ++++ b/src/gclue-location.c +@@ -477,6 +477,17 @@ parse_coordinate_string (const char *coordinate, + return out; + } + ++static gboolean ++coordinates_ok (double latitude, ++ double longitude) ++{ ++ if (latitude > 90.0 || latitude < -90 || ++ longitude > 180.0 || longitude < -180.0) ++ return FALSE; ++ else ++ return TRUE; ++} ++ + static gdouble + parse_altitude_string (const char *altitude, + const char *unit) +@@ -631,8 +642,9 @@ gclue_location_create_from_gga (const char *gga) + timestamp = parse_nmea_timestamp (parts[1]); + latitude = parse_coordinate_string (parts[2], parts[3]); + longitude = parse_coordinate_string (parts[4], parts[5]); +- if (latitude == INVALID_COORDINATE || longitude == INVALID_COORDINATE) { +- g_warning ("Invalid coordinate on NMEA GGA sentence."); ++ if (!coordinates_ok (latitude, longitude)) { ++ g_warning ("Invalid coordinates (%f, %f) on NMEA GGA sentence.", ++ latitude, longitude); + return NULL; + } + +@@ -677,9 +689,9 @@ gclue_location_create_from_rmc (const char *rmc, + guint64 timestamp = parse_nmea_timestamp (parts[1]); + gdouble lat = parse_coordinate_string (parts[3], parts[4]); + gdouble lon = parse_coordinate_string (parts[5], parts[6]); +- +- if (lat == INVALID_COORDINATE || lon == INVALID_COORDINATE) { +- g_warning ("Invalid coordinate on NMEA RMC sentence."); ++ if (!coordinates_ok (lat, lon)) { ++ g_warning ("Invalid coordinates (%f, %f) on NMEA RMC sentence.", ++ lat, lon); + return NULL; + } + +-- +2.48.1 + + +From 32101976945e51536aff3b6945c12ec4d15dd203 Mon Sep 17 00:00:00 2001 +From: Chris Talbot +Date: Thu, 5 Dec 2024 06:58:48 -0700 +Subject: [PATCH] Web-Source: Set User-Agent on Soup Session Construction + +Also add OS Info to user-agent +--- + src/gclue-mozilla.c | 6 ------ + src/gclue-web-source.c | 30 ++++++++++++++++++++++++++++++ + 2 files changed, 30 insertions(+), 6 deletions(-) + +diff --git a/src/gclue-mozilla.c b/src/gclue-mozilla.c +index 2b3467d..5680e45 100644 +--- a/src/gclue-mozilla.c ++++ b/src/gclue-mozilla.c +@@ -174,8 +174,6 @@ towertec_to_radiotype (GClueTowerTec tec, + return TRUE; + } + +-#define USER_AGENT (PACKAGE_NAME "/" PACKAGE_VERSION) +- + SoupMessage * + gclue_mozilla_create_query (GClueMozilla *mozilla, + gboolean skip_tower, +@@ -185,7 +183,6 @@ gclue_mozilla_create_query (GClueMozilla *mozilla, + { + gboolean has_tower = FALSE, has_bss = FALSE; + SoupMessage *ret = NULL; +- SoupMessageHeaders *request_headers; + JsonBuilder *builder; + g_autoptr(GList) bss_list = NULL; + JsonGenerator *generator; +@@ -300,8 +297,6 @@ gclue_mozilla_create_query (GClueMozilla *mozilla, + + uri = gclue_mozilla_get_locate_url (mozilla); + ret = soup_message_new ("POST", uri); +- request_headers = soup_message_get_request_headers (ret); +- soup_message_headers_replace (request_headers, "User-Agent", USER_AGENT); + body = g_bytes_new_take (data, data_len); + soup_message_set_request_body_from_bytes (ret, "application/json", body); + g_debug ("Sending following request to '%s':\n%s", uri, data); +@@ -566,7 +561,6 @@ gclue_mozilla_create_submit_query (GClueMozilla *mozilla, + + ret = soup_message_new ("POST", url); + request_headers = soup_message_get_request_headers (ret); +- soup_message_headers_replace (request_headers, "User-Agent", USER_AGENT); + if (nick != NULL && nick[0] != '\0') + soup_message_headers_append (request_headers, + "X-Nickname", +diff --git a/src/gclue-web-source.c b/src/gclue-web-source.c +index 92d94b8..56d511b 100644 +--- a/src/gclue-web-source.c ++++ b/src/gclue-web-source.c +@@ -28,6 +28,7 @@ + #include "gclue-error.h" + #include "gclue-location.h" + #include "gclue-mozilla.h" ++#include "config.h" + + /** + * SECTION:gclue-web-source +@@ -402,16 +403,45 @@ gclue_web_source_finalize (GObject *gsource) + G_OBJECT_CLASS (gclue_web_source_parent_class)->finalize (gsource); + } + ++static char * ++get_os_info (void) ++{ ++ g_autofree char *pretty_name = NULL; ++ g_autofree char *os_name = g_get_os_info (G_OS_INFO_KEY_NAME); ++ g_autofree char *os_version = g_get_os_info (G_OS_INFO_KEY_VERSION); ++ ++ if (os_name && os_version) ++ return g_strdup_printf ("%s; %s", os_name, os_version); ++ ++ pretty_name = g_get_os_info (G_OS_INFO_KEY_PRETTY_NAME); ++ if (pretty_name) ++ return g_steal_pointer (&pretty_name); ++ ++ /* Translators: Not marked as translatable as debug output should stay English */ ++ return g_strdup ("Unknown"); ++} ++ ++#define USER_AGENT (PACKAGE_NAME "/" PACKAGE_VERSION) ++ ++static char * ++get_user_agent (void) ++{ ++ g_autofree char *os_info = get_os_info (); ++ return g_strdup_printf ("%s (%s)", USER_AGENT, os_info); ++} ++ + static void + gclue_web_source_constructed (GObject *object) + { + GNetworkMonitor *monitor; + GClueWebSourcePrivate *priv = GCLUE_WEB_SOURCE (object)->priv; ++ g_autofree char *user_agent = get_user_agent (); + + G_OBJECT_CLASS (gclue_web_source_parent_class)->constructed (object); + + priv->soup_session = soup_session_new (); + soup_session_set_proxy_resolver (priv->soup_session, NULL); ++ soup_session_set_user_agent (priv->soup_session, user_agent); + + monitor = g_network_monitor_get_default (); + priv->network_changed_id = +-- +2.48.1 + + +From 1db3827daab03ea5ab95500d1db9733b6fc2240b Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Tue, 27 Aug 2024 12:07:40 +0300 +Subject: [PATCH] Return a correct enum from LocationSource stop method + implementations + +--- + src/gclue-3g.c | 3 ++- + src/gclue-cdma.c | 3 ++- + src/gclue-locator.c | 4 +++- + src/gclue-modem-gps.c | 3 ++- + src/gclue-nmea-source.c | 3 ++- + src/gclue-wifi.c | 3 ++- + 6 files changed, 13 insertions(+), 6 deletions(-) + +diff --git a/src/gclue-3g.c b/src/gclue-3g.c +index 225b706..90cd5e5 100644 +--- a/src/gclue-3g.c ++++ b/src/gclue-3g.c +@@ -409,7 +409,8 @@ gclue_3g_stop (GClueLocationSource *source) + g_autoptr(GError) error = NULL; + GClueLocationSourceStopResult base_result; + +- g_return_val_if_fail (GCLUE_IS_LOCATION_SOURCE (source), FALSE); ++ g_return_val_if_fail (GCLUE_IS_LOCATION_SOURCE (source), ++ GCLUE_LOCATION_SOURCE_STOP_RESULT_FAILED); + + base_class = GCLUE_LOCATION_SOURCE_CLASS (gclue_3g_parent_class); + base_result = base_class->stop (source); +diff --git a/src/gclue-cdma.c b/src/gclue-cdma.c +index 75bd5a0..4c992e5 100644 +--- a/src/gclue-cdma.c ++++ b/src/gclue-cdma.c +@@ -246,7 +246,8 @@ gclue_cdma_stop (GClueLocationSource *source) + g_autoptr(GError) error = NULL; + GClueLocationSourceStopResult base_result; + +- g_return_val_if_fail (GCLUE_IS_LOCATION_SOURCE (source), FALSE); ++ g_return_val_if_fail (GCLUE_IS_LOCATION_SOURCE (source), ++ GCLUE_LOCATION_SOURCE_STOP_RESULT_FAILED); + + base_class = GCLUE_LOCATION_SOURCE_CLASS (gclue_cdma_parent_class); + base_result = base_class->stop (source); +diff --git a/src/gclue-locator.c b/src/gclue-locator.c +index d6ed560..083ebe6 100644 +--- a/src/gclue-locator.c ++++ b/src/gclue-locator.c +@@ -569,7 +569,9 @@ gclue_locator_stop (GClueLocationSource *source) + GList *node; + GClueLocationSourceStopResult base_result; + +- g_return_val_if_fail (GCLUE_IS_LOCATOR (source), FALSE); ++ g_return_val_if_fail (GCLUE_IS_LOCATOR (source), ++ GCLUE_LOCATION_SOURCE_STOP_RESULT_FAILED); ++ + locator = GCLUE_LOCATOR (source); + + base_class = GCLUE_LOCATION_SOURCE_CLASS (gclue_locator_parent_class); +diff --git a/src/gclue-modem-gps.c b/src/gclue-modem-gps.c +index 5b348d2..a187aab 100644 +--- a/src/gclue-modem-gps.c ++++ b/src/gclue-modem-gps.c +@@ -265,7 +265,8 @@ gclue_modem_gps_stop (GClueLocationSource *source) + g_autoptr(GError) error = NULL; + GClueLocationSourceStopResult base_result; + +- g_return_val_if_fail (GCLUE_IS_LOCATION_SOURCE (source), FALSE); ++ g_return_val_if_fail (GCLUE_IS_LOCATION_SOURCE (source), ++ GCLUE_LOCATION_SOURCE_STOP_RESULT_FAILED); + + base_class = GCLUE_LOCATION_SOURCE_CLASS (gclue_modem_gps_parent_class); + base_result = base_class->stop (source); +diff --git a/src/gclue-nmea-source.c b/src/gclue-nmea-source.c +index 13ada66..e17d65a 100644 +--- a/src/gclue-nmea-source.c ++++ b/src/gclue-nmea-source.c +@@ -1109,7 +1109,8 @@ gclue_nmea_source_stop (GClueLocationSource *source) + GClueLocationSourceClass *base_class; + GClueLocationSourceStopResult base_result; + +- g_return_val_if_fail (GCLUE_IS_NMEA_SOURCE (source), FALSE); ++ g_return_val_if_fail (GCLUE_IS_NMEA_SOURCE (source), ++ GCLUE_LOCATION_SOURCE_STOP_RESULT_FAILED); + + base_class = GCLUE_LOCATION_SOURCE_CLASS (gclue_nmea_source_parent_class); + base_result = base_class->stop (source); +diff --git a/src/gclue-wifi.c b/src/gclue-wifi.c +index cd20b0d..0649ef0 100644 +--- a/src/gclue-wifi.c ++++ b/src/gclue-wifi.c +@@ -846,7 +846,8 @@ gclue_wifi_stop (GClueLocationSource *source) + GClueLocationSourceClass *base_class; + GClueLocationSourceStopResult base_result; + +- g_return_val_if_fail (GCLUE_IS_WIFI (source), FALSE); ++ g_return_val_if_fail (GCLUE_IS_WIFI (source), ++ GCLUE_LOCATION_SOURCE_STOP_RESULT_FAILED); + + base_class = GCLUE_LOCATION_SOURCE_CLASS (gclue_wifi_parent_class); + base_result = base_class->stop (source); +-- +2.48.1 + + +From 420a5b06cb57c147949b906f78171b708ab6269a Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Tue, 27 Aug 2024 10:41:53 +0300 +Subject: [PATCH] where-am-i: Output accuracy without unnecessary decimals + +--- + demo/where-am-i.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/demo/where-am-i.c b/demo/where-am-i.c +index 8324058..bff89f0 100644 +--- a/demo/where-am-i.c ++++ b/demo/where-am-i.c +@@ -88,7 +88,7 @@ print_location (GClueSimple *simple) + + location = gclue_simple_get_location (simple); + g_print ("\nNew location:\n"); +- g_print ("Latitude: %f°\nLongitude: %f°\nAccuracy: %f meters\n", ++ g_print ("Latitude: %f°\nLongitude: %f°\nAccuracy: %.0f meters\n", + gclue_location_get_latitude (location), + gclue_location_get_longitude (location), + gclue_location_get_accuracy (location)); +-- +2.48.1 + + +From 253983f1061ad647605a273bce1acea94bc63aa6 Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Mon, 26 Aug 2024 16:04:05 +0300 +Subject: [PATCH] meson: Fix typos in meson_options.txt + +--- + meson_options.txt | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/meson_options.txt b/meson_options.txt +index 4d55a63..a7f34b7 100644 +--- a/meson_options.txt ++++ b/meson_options.txt +@@ -12,13 +12,13 @@ option('gtk-doc', + description: 'Whether to generate the API reference for Geocode-GLib') + option('3g-source', + type: 'boolean', value: true, +- description: 'Enable 3G source (requires ModemManager') ++ description: 'Enable 3G source (requires ModemManager)') + option('cdma-source', + type: 'boolean', value: true, +- description: 'Enable CDMA source (requires ModemManager') ++ description: 'Enable CDMA source (requires ModemManager)') + option('modem-gps-source', + type: 'boolean', value: true, +- description: 'Enable modem GPS source (requires ModemManager') ++ description: 'Enable modem GPS source (requires ModemManager)') + option('nmea-source', + type: 'boolean', value: true, + description: 'Enable network NMEA source (requires Avahi libraries)') +-- +2.48.1 + + +From d148ff47bb3fd86df34e8d4ea9595c6c919cb213 Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Mon, 26 Aug 2024 15:49:50 +0300 +Subject: [PATCH] meson, locator: Add 'wifi-source' compilation option + +Allows disabling the WiFi source during compilation. +--- + meson.build | 13 ++++++++----- + meson_options.txt | 3 +++ + src/gclue-locator.c | 9 +++++++-- + 3 files changed, 18 insertions(+), 7 deletions(-) + +diff --git a/meson.build b/meson.build +index c561572..4cef412 100644 +--- a/meson.build ++++ b/meson.build +@@ -32,6 +32,7 @@ conf.set_quoted('LOCALEDIR', localedir) + conf.set_quoted('SYSCONFDIR', sysconfdir) + conf.set_quoted('DEFAULT_WIFI_URL', get_option('default-wifi-url')) + conf.set_quoted('DEFAULT_WIFI_SUBMIT_URL', get_option('default-wifi-submit-url')) ++conf.set10('GCLUE_USE_WIFI_SOURCE', get_option('wifi-source')) + conf.set10('GCLUE_USE_3G_SOURCE', get_option('3g-source')) + conf.set10('GCLUE_USE_CDMA_SOURCE', get_option('cdma-source')) + conf.set10('GCLUE_USE_MODEM_GPS_SOURCE', get_option('modem-gps-source')) +@@ -90,11 +91,12 @@ summary = ''' + Backend: @4@ + Convenience library: @5@ + Introspection: @6@ +- 3G source: @7@ +- CDMA source: @8@ +- Modem GPS source: @9@ +- Network NMEA source: @10@ +- Compass: @11@ ++ WiFi source: @7@ ++ 3G source: @8@ ++ CDMA source: @9@ ++ Modem GPS source: @10@ ++ Network NMEA source: @11@ ++ Compass: @12@ + '''.format(gclue_version, + get_option('prefix'), + cc.get_id(), +@@ -102,6 +104,7 @@ summary = ''' + get_option('enable-backend'), + get_option('libgeoclue'), + get_option('introspection'), ++ get_option('wifi-source'), + get_option('3g-source'), + get_option('cdma-source'), + get_option('modem-gps-source'), +diff --git a/meson_options.txt b/meson_options.txt +index a7f34b7..708d32a 100644 +--- a/meson_options.txt ++++ b/meson_options.txt +@@ -10,6 +10,9 @@ option('vapi', + option('gtk-doc', + type: 'boolean', value: true, + description: 'Whether to generate the API reference for Geocode-GLib') ++option('wifi-source', ++ type: 'boolean', value: true, ++ description: 'Enable WiFi source') + option('3g-source', + type: 'boolean', value: true, + description: 'Enable 3G source (requires ModemManager)') +diff --git a/src/gclue-locator.c b/src/gclue-locator.c +index 083ebe6..4e5c1b9 100644 +--- a/src/gclue-locator.c ++++ b/src/gclue-locator.c +@@ -29,9 +29,12 @@ + #include "gclue-locator.h" + + #include "gclue-static-source.h" +-#include "gclue-wifi.h" + #include "gclue-config.h" + ++#if GCLUE_USE_WIFI_SOURCE ++#include "gclue-wifi.h" ++#endif ++ + #if GCLUE_USE_3G_SOURCE + #include "gclue-3g.h" + #endif +@@ -400,7 +403,6 @@ gclue_locator_constructed (GObject *object) + GClueLocator *locator = GCLUE_LOCATOR (object); + GClueLocationSource *submit_source = NULL; + GClueConfig *gconfig = gclue_config_get_singleton (); +- GClueWifi *wifi = NULL; + GList *node; + GClueMinUINT *threshold; + +@@ -420,6 +422,8 @@ gclue_locator_constructed (GObject *object) + cdma); + } + #endif ++#if GCLUE_USE_WIFI_SOURCE ++ GClueWifi *wifi = NULL; + if (gclue_config_get_enable_wifi_source (gconfig)) { + wifi = gclue_wifi_get_singleton (locator->priv->accuracy_level); + } else { +@@ -434,6 +438,7 @@ gclue_locator_constructed (GObject *object) + locator->priv->sources = g_list_append (locator->priv->sources, + wifi); + } ++#endif + #if GCLUE_USE_MODEM_GPS_SOURCE + if (gclue_config_get_enable_modem_gps_source (gconfig)) { + GClueModemGPS *gps = gclue_modem_gps_get_singleton (); +-- +2.48.1 + + +From 1b2ca74cf3200d24787c29508d5c69e4ac0b899a Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Sat, 31 Aug 2024 21:26:25 +0300 +Subject: [PATCH] meson, locator: Add 'static-source' compilation option + +--- + meson.build | 5 ++++- + meson_options.txt | 3 +++ + src/gclue-locator.c | 8 ++++++-- + 3 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/meson.build b/meson.build +index 4cef412..74f7578 100644 +--- a/meson.build ++++ b/meson.build +@@ -37,6 +37,7 @@ conf.set10('GCLUE_USE_3G_SOURCE', get_option('3g-source')) + conf.set10('GCLUE_USE_CDMA_SOURCE', get_option('cdma-source')) + conf.set10('GCLUE_USE_MODEM_GPS_SOURCE', get_option('modem-gps-source')) + conf.set10('GCLUE_USE_NMEA_SOURCE', get_option('nmea-source')) ++conf.set10('GCLUE_USE_STATIC_SOURCE', get_option('static-source')) + conf.set10('GCLUE_USE_COMPASS', get_option('compass')) + + configure_file(output: 'config.h', configuration : conf) +@@ -96,7 +97,8 @@ summary = ''' + CDMA source: @9@ + Modem GPS source: @10@ + Network NMEA source: @11@ +- Compass: @12@ ++ Static source: @12@ ++ Compass: @13@ + '''.format(gclue_version, + get_option('prefix'), + cc.get_id(), +@@ -109,5 +111,6 @@ summary = ''' + get_option('cdma-source'), + get_option('modem-gps-source'), + get_option('nmea-source'), ++ get_option('static-source'), + get_option('compass')) + message(summary) +diff --git a/meson_options.txt b/meson_options.txt +index 708d32a..76825d0 100644 +--- a/meson_options.txt ++++ b/meson_options.txt +@@ -25,6 +25,9 @@ option('modem-gps-source', + option('nmea-source', + type: 'boolean', value: true, + description: 'Enable network NMEA source (requires Avahi libraries)') ++option('static-source', ++ type: 'boolean', value: true, ++ description: 'Enable static source (geolocation file)') + option('compass', + type: 'boolean', value: true, + description: 'Enable setting heading from net.hadess.SensorProxy compass') +diff --git a/src/gclue-locator.c b/src/gclue-locator.c +index 4e5c1b9..7b0aefa 100644 +--- a/src/gclue-locator.c ++++ b/src/gclue-locator.c +@@ -28,7 +28,6 @@ + + #include "gclue-locator.h" + +-#include "gclue-static-source.h" + #include "gclue-config.h" + + #if GCLUE_USE_WIFI_SOURCE +@@ -51,6 +50,10 @@ + #include "gclue-nmea-source.h" + #endif + ++#if GCLUE_USE_STATIC_SOURCE ++#include "gclue-static-source.h" ++#endif ++ + /* This class is like a master location source that hides all individual + * location sources from rest of the code + */ +@@ -460,7 +463,7 @@ gclue_locator_constructed (GObject *object) + + } + #endif +- ++#if GCLUE_USE_STATIC_SOURCE + if (gclue_config_get_enable_static_source (gconfig)) { + GClueStaticSource *static_source; + +@@ -469,6 +472,7 @@ gclue_locator_constructed (GObject *object) + locator->priv->sources = g_list_append (locator->priv->sources, + static_source); + } ++#endif + + for (node = locator->priv->sources; node != NULL; node = node->next) { + g_signal_connect (G_OBJECT (node->data), +-- +2.48.1 + + +From 2cd5108cfdad9a2227777cbd87ade2e0ede90f97 Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Tue, 3 Sep 2024 12:28:10 +0300 +Subject: [PATCH] config: Warn when enabling a compile-time disabled source + +--- + src/gclue-config.c | 42 ++++++++++++++++++++++++++++++++++-------- + 1 file changed, 34 insertions(+), 8 deletions(-) + +diff --git a/src/gclue-config.c b/src/gclue-config.c +index acd6009..0691f47 100644 +--- a/src/gclue-config.c ++++ b/src/gclue-config.c +@@ -20,8 +20,9 @@ + * Authors: Zeeshan Ali (Khattak) + */ + ++#include "config.h" ++ + #include +-#include + #include + + #include "gclue-config.h" +@@ -303,6 +304,31 @@ error_out: + } + } + ++static gboolean ++load_enable_source (GClueConfig *config, ++ const gchar *group_name, ++ gboolean compiled, ++ gboolean *value_storage) ++{ ++ gboolean enabled; ++ ++ g_return_val_if_fail (value_storage != NULL, FALSE); ++ ++ if (!load_boolean_value (config, group_name, "enable", &enabled)) ++ return FALSE; ++ ++ if (enabled && !compiled) { ++ g_warning ("Source '%s' is enabled in configuration, " ++ "but Geoclue is compiled without it", ++ group_name); ++ *value_storage = FALSE; ++ } else { ++ *value_storage = enabled; ++ } ++ ++ return TRUE; ++} ++ + #define DEFAULT_WIFI_SUBMIT_NICK "geoclue" + + static void +@@ -311,7 +337,7 @@ load_wifi_config (GClueConfig *config) + GClueConfigPrivate *priv = config->priv; + g_autofree gchar *wifi_submit_nick = NULL; + +- load_boolean_value (config, "wifi", "enable", ++ load_enable_source (config, "wifi", GCLUE_USE_WIFI_SOURCE, + &priv->enable_wifi_source); + + load_string_value (config, "wifi", "url", &priv->wifi_url); +@@ -338,28 +364,28 @@ load_wifi_config (GClueConfig *config) + static void + load_3g_config (GClueConfig *config) + { +- load_boolean_value (config, "3g", "enable", ++ load_enable_source (config, "3g", GCLUE_USE_3G_SOURCE, + &config->priv->enable_3g_source); + } + + static void + load_cdma_config (GClueConfig *config) + { +- load_boolean_value (config, "cdma", "enable", ++ load_enable_source (config, "cdma", GCLUE_USE_CDMA_SOURCE, + &config->priv->enable_cdma_source); + } + + static void + load_modem_gps_config (GClueConfig *config) + { +- load_boolean_value (config, "modem-gps", "enable", ++ load_enable_source (config, "modem-gps", GCLUE_USE_MODEM_GPS_SOURCE, + &config->priv->enable_modem_gps_source); + } + + static void + load_network_nmea_config (GClueConfig *config) + { +- load_boolean_value (config, "network-nmea", "enable", ++ load_enable_source (config, "network-nmea", GCLUE_USE_NMEA_SOURCE, + &config->priv->enable_nmea_source); + load_string_value (config, "network-nmea", "nmea-socket", + &config->priv->nmea_socket); +@@ -368,14 +394,14 @@ load_network_nmea_config (GClueConfig *config) + static void + load_compass_config (GClueConfig *config) + { +- load_boolean_value (config, "compass", "enable", ++ load_enable_source (config, "compass", GCLUE_USE_COMPASS, + &config->priv->enable_compass); + } + + static void + load_static_source_config (GClueConfig *config) + { +- load_boolean_value (config, "static-source", "enable", ++ load_enable_source (config, "static-source", GCLUE_USE_STATIC_SOURCE, + &config->priv->enable_static_source); + } + +-- +2.48.1 + + +From b598f3725a2622bb6f1accf37a99894539df9880 Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Sun, 5 Jan 2025 16:11:10 +0200 +Subject: [PATCH] locator: Prevent segfault on + refresh_available_accuracy_level() + +If the location source list of the locator is empty, do not try access +the first element, but use GCLUE_ACCURACY_LEVEL_NONE as the best +accuracy. +--- + src/gclue-locator.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/gclue-locator.c b/src/gclue-locator.c +index 7b0aefa..74089b3 100644 +--- a/src/gclue-locator.c ++++ b/src/gclue-locator.c +@@ -213,8 +213,10 @@ refresh_available_accuracy_level (GClueLocator *locator) + (locator->priv->sources, + (GCompareFunc) compare_accuracy_level); + +- new = gclue_location_source_get_available_accuracy_level +- (GCLUE_LOCATION_SOURCE (locator->priv->sources->data)); ++ new = locator->priv->sources ? ++ gclue_location_source_get_available_accuracy_level ++ (GCLUE_LOCATION_SOURCE (locator->priv->sources->data)) : ++ GCLUE_ACCURACY_LEVEL_NONE; + + existing = gclue_location_source_get_available_accuracy_level + (GCLUE_LOCATION_SOURCE (locator)); +-- +2.48.1 + + +From 6eebfc8347919193f324f42c44a48cc7fd89585d Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Sun, 5 Jan 2025 16:41:06 +0200 +Subject: [PATCH] locator: Warn when no location sources are available + +--- + src/gclue-locator.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/gclue-locator.c b/src/gclue-locator.c +index 74089b3..d6aa347 100644 +--- a/src/gclue-locator.c ++++ b/src/gclue-locator.c +@@ -476,6 +476,11 @@ gclue_locator_constructed (GObject *object) + } + #endif + ++ if (locator->priv->sources == NULL) { ++ g_warning ("No sources enabled in configuration, " ++ "location not available"); ++ } ++ + for (node = locator->priv->sources; node != NULL; node = node->next) { + g_signal_connect (G_OBJECT (node->data), + "notify::available-accuracy-level", +-- +2.48.1 + + +From 1ca16fe0bbea345babb9713451ab330c31e959ed Mon Sep 17 00:00:00 2001 +From: "Maciej S. Szmigiero" +Date: Mon, 6 Jan 2025 15:02:18 +0100 +Subject: [PATCH] modem-manager: Fix crash on removing a modem without location + capabilities + +on_mm_object_removed () should obviously act on the modem object that this +notification pertains to, not the currently in-use modem. + +If there was only a modem without location capabilities present then +priv->mm_object was NULL so the code would crash on a NULL pointer +dereference. +--- + src/gclue-modem-manager.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/gclue-modem-manager.c b/src/gclue-modem-manager.c +index e6ee823..27ea191 100644 +--- a/src/gclue-modem-manager.c ++++ b/src/gclue-modem-manager.c +@@ -944,7 +944,7 @@ on_mm_object_removed (GDBusObjectManager *object_manager, + MMObject *mm_object = MM_OBJECT (object); + GClueModemManager *manager = GCLUE_MODEM_MANAGER (user_data); + GClueModemManagerPrivate *priv = manager->priv; +- const char *path = mm_object_get_path (priv->mm_object); ++ const char *path = mm_object_get_path (mm_object); + + g_hash_table_remove (manager->priv->modems_not_enabled, path); + +-- +2.48.1 + + +From ca898d54a63aa6216ebdec4472a6bbb71b8bde5b Mon Sep 17 00:00:00 2001 +From: Chris Talbot +Date: Sun, 22 Dec 2024 09:34:29 -0700 +Subject: [PATCH] conf.in: Define wifi URLs in conf if in options + +--- + data/geoclue.conf.in | 5 ++++- + data/meson.build | 8 ++++++++ + 2 files changed, 12 insertions(+), 1 deletion(-) + +diff --git a/data/geoclue.conf.in b/data/geoclue.conf.in +index 7298353..8225ceb 100644 +--- a/data/geoclue.conf.in ++++ b/data/geoclue.conf.in +@@ -50,7 +50,8 @@ enable=@default_wifi_enable@ + # URL to a WiFi geolocation service compatible with the Ichnaea API + # (https://ichnaea.readthedocs.io/en/latest/api/geolocate.html). + # An API key can be set by using the 'key' URL parameter. +-# If unset, defaults to a location service defined at build-time. ++# If unset, defaults to an URL defined at build-time, ++# this URL is '@default_wifi_url@'' + #url=https://example.com/v1/geolocate?key=YOUR_KEY + + # To use the Positon geolocation service, uncomment this URL. +@@ -98,6 +99,8 @@ submit-data=false + + # URL to submit data to a WiFi geolocation service with an Ichnaea compatible API + # (https://ichnaea.readthedocs.io/en/latest/api/geosubmit2.html). ++# If unset, defaults to an URL defined at build-time, ++# this URL is '@default_wifi_submit_url@'. + #submission-url=https://example.com/v2/geosubmit?key=YOUR_KEY + + # A nickname to submit network data with. If empty, omitted from the submission. +diff --git a/data/meson.build b/data/meson.build +index b22ff55..abbdeb5 100644 +--- a/data/meson.build ++++ b/data/meson.build +@@ -8,10 +8,18 @@ if get_option('enable-backend') + conf.set('demo_agent', '') + endif + ++ if get_option('default-wifi-submit-url') != '' ++ conf.set('default_wifi_submit_url', get_option('default-wifi-submit-url')) ++ else ++ conf.set('default_wifi_submit_url', '') ++ endif ++ + if get_option('default-wifi-url') != '' + conf.set('default_wifi_enable', 'true') ++ conf.set('default_wifi_url', get_option('default-wifi-url')) + else + conf.set('default_wifi_enable', 'false') ++ conf.set('default_wifi_url', '') + endif + + conf_dir = join_paths(sysconfdir, 'geoclue') +-- +2.48.1 + + +From 6b439905fc85b0bd0bcfe2f00afed834b552322d Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Mon, 13 Jan 2025 21:25:51 +0200 +Subject: [PATCH] conf.in: Add BeaconDB example URL to wifi section + +--- + data/geoclue.conf.in | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/data/geoclue.conf.in b/data/geoclue.conf.in +index 8225ceb..c0e876e 100644 +--- a/data/geoclue.conf.in ++++ b/data/geoclue.conf.in +@@ -54,6 +54,9 @@ enable=@default_wifi_enable@ + # this URL is '@default_wifi_url@'' + #url=https://example.com/v1/geolocate?key=YOUR_KEY + ++# To use the BeaconDB geolocation service, uncomment this URL. ++#url=https://api.beacondb.net/v1/geolocate ++ + # To use the Positon geolocation service, uncomment this URL. + # + # NOTE: Distributors of geoclue may only uncomment this URL if the +-- +2.48.1 + + +From 9b83129401ad65c053e626ee75423a3666751299 Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Thu, 22 Aug 2024 16:30:17 +0300 +Subject: [PATCH] web,mozilla: Add gclue_mozilla_parse_submit_response to parse + Ichnaea submit response + +--- + src/gclue-mozilla.c | 8 ++++++++ + src/gclue-mozilla.h | 4 ++++ + src/gclue-web-source.c | 5 ++++- + 3 files changed, 16 insertions(+), 1 deletion(-) + +diff --git a/src/gclue-mozilla.c b/src/gclue-mozilla.c +index 5680e45..ae35399 100644 +--- a/src/gclue-mozilla.c ++++ b/src/gclue-mozilla.c +@@ -383,6 +383,14 @@ gclue_mozilla_parse_response (const char *json, + return location; + } + ++gboolean ++gclue_mozilla_parse_submit_response (const char *response_contents, ++ gboolean status_code, ++ GError **error) ++{ ++ return status_code != SOUP_STATUS_OK && status_code != SOUP_STATUS_NO_CONTENT; ++} ++ + const char * + gclue_mozilla_get_submit_url (GClueMozilla *mozilla) + { +diff --git a/src/gclue-mozilla.h b/src/gclue-mozilla.h +index a8010b0..845c73f 100644 +--- a/src/gclue-mozilla.h ++++ b/src/gclue-mozilla.h +@@ -91,6 +91,10 @@ gclue_mozilla_create_submit_query (GClueMozilla *mozilla, + GClueLocation *location, + GError **error); + gboolean ++gclue_mozilla_parse_submit_response (const char *response_contents, ++ gboolean status_code, ++ GError **error); ++gboolean + gclue_mozilla_should_ignore_bss (WPABSS *bss); + + const char *gclue_mozilla_get_locate_url (GClueMozilla *mozilla); +diff --git a/src/gclue-web-source.c b/src/gclue-web-source.c +index 56d511b..0739690 100644 +--- a/src/gclue-web-source.c ++++ b/src/gclue-web-source.c +@@ -550,6 +550,7 @@ submit_query_callback (SoupSession *session, + { + g_autoptr(GBytes) body = NULL; + g_autoptr(GError) local_error = NULL; ++ g_autofree char *contents = NULL; + SoupMessage *query; + g_autofree char *uri_str = NULL; + gint status_code; +@@ -563,9 +564,11 @@ submit_query_callback (SoupSession *session, + uri_str, local_error->message); + return; + } ++ contents = g_strndup (g_bytes_get_data (body, NULL), g_bytes_get_size (body)); + + status_code = soup_message_get_status (query); +- if (status_code != SOUP_STATUS_OK && status_code != SOUP_STATUS_NO_CONTENT) { ++ ++ if (!gclue_mozilla_parse_submit_response (contents, status_code, NULL)) { + g_warning ("Failed to submit location data to '%s': %s", + uri_str, soup_message_get_reason_phrase (query)); + return; +-- +2.48.1 + + +From 8205af59444892ff983edff7b24b31913c67f74a Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Mon, 26 Aug 2024 23:27:09 +0300 +Subject: [PATCH] web: Add gclue_web_source_get_query_data_description() method + +--- + src/gclue-web-source.c | 6 ++++++ + src/gclue-web-source.h | 2 ++ + 2 files changed, 8 insertions(+) + +diff --git a/src/gclue-web-source.c b/src/gclue-web-source.c +index 0739690..fb4008a 100644 +--- a/src/gclue-web-source.c ++++ b/src/gclue-web-source.c +@@ -666,3 +666,9 @@ gclue_web_source_set_submit_url (GClueWebSource *source, + { + source->priv->submit_url = url; + } ++ ++const char *gclue_web_source_get_query_data_description ++ (GClueWebSource *source) ++{ ++ return source->priv->query_data_description; ++} +diff --git a/src/gclue-web-source.h b/src/gclue-web-source.h +index 05068c6..9cc5d31 100644 +--- a/src/gclue-web-source.h ++++ b/src/gclue-web-source.h +@@ -88,6 +88,8 @@ void gclue_web_source_set_locate_url (GClueWebSource *source, + const char *url); + void gclue_web_source_set_submit_url (GClueWebSource *source, + const char *url); ++const char *gclue_web_source_get_query_data_description ++ (GClueWebSource *source); + + G_END_DECLS + +-- +2.48.1 + + +From 0ff18d0a7c6c962d05bb7f5e1cf2b54c49c5b7c9 Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Thu, 22 Aug 2024 22:51:21 +0300 +Subject: [PATCH] web, 3g, wifi: Add parse_response() and + parse_submit_response() vfuncs + +Add these methods to 3g and wifi classes, they are shim functions to +gclue_mozilla_parse_response and gclue_mozilla_parse_submit_response. +--- + src/gclue-3g.c | 22 ++++++++++++++++++++++ + src/gclue-web-source.c | 10 ++++++---- + src/gclue-web-source.h | 8 ++++++++ + src/gclue-wifi.c | 24 +++++++++++++++++++++++- + 4 files changed, 59 insertions(+), 5 deletions(-) + +diff --git a/src/gclue-3g.c b/src/gclue-3g.c +index 90cd5e5..01f9ae2 100644 +--- a/src/gclue-3g.c ++++ b/src/gclue-3g.c +@@ -128,6 +128,26 @@ static void cancel_location_3gpp_timeout (GClue3G *g3g) + priv->location_3gpp_timeout_id = 0; + } + ++static GClueLocation * ++gclue_3g_parse_response (GClueWebSource *source, ++ const char *content, ++ GError **error) ++{ ++ const char *location_description = ++ gclue_web_source_get_query_data_description (source); ++ ++ return gclue_mozilla_parse_response (content, location_description, error); ++} ++ ++static gboolean ++gclue_3g_parse_submit_response (GClueWebSource *source, ++ const char *content, ++ gboolean status_code, ++ GError **error) ++{ ++ return gclue_mozilla_parse_submit_response (content, status_code, error); ++} ++ + static void + gclue_3g_finalize (GObject *g3g) + { +@@ -161,7 +181,9 @@ gclue_3g_class_init (GClue3GClass *klass) + source_class->start = gclue_3g_start; + source_class->stop = gclue_3g_stop; + web_class->create_query = gclue_3g_create_query; ++ web_class->parse_response = gclue_3g_parse_response; + web_class->create_submit_query = gclue_3g_create_submit_query; ++ web_class->parse_submit_response = gclue_3g_parse_submit_response; + web_class->get_available_accuracy_level = + gclue_3g_get_available_accuracy_level; + } +diff --git a/src/gclue-web-source.c b/src/gclue-web-source.c +index fb4008a..8cd650f 100644 +--- a/src/gclue-web-source.c ++++ b/src/gclue-web-source.c +@@ -161,9 +161,9 @@ refresh_callback (SoupSession *session, + uri = soup_message_get_uri (query); + str = g_uri_to_string (uri); + g_debug ("Got following response from '%s':\n%s", str, contents); +- location = gclue_mozilla_parse_response (contents, +- web->priv->query_data_description, +- &local_error); ++ location = GCLUE_WEB_SOURCE_GET_CLASS (web)->parse_response (web, ++ contents, ++ &local_error); + if (local_error != NULL) { + g_task_return_error (task, g_steal_pointer (&local_error)); + return; +@@ -548,6 +548,7 @@ submit_query_callback (SoupSession *session, + GAsyncResult *result, + gpointer user_data) + { ++ GClueWebSource *web = GCLUE_WEB_SOURCE (user_data); + g_autoptr(GBytes) body = NULL; + g_autoptr(GError) local_error = NULL; + g_autofree char *contents = NULL; +@@ -568,7 +569,8 @@ submit_query_callback (SoupSession *session, + + status_code = soup_message_get_status (query); + +- if (!gclue_mozilla_parse_submit_response (contents, status_code, NULL)) { ++ if (!GCLUE_WEB_SOURCE_GET_CLASS (web)->parse_submit_response ++ (web, contents, status_code, &local_error)) { + g_warning ("Failed to submit location data to '%s': %s", + uri_str, soup_message_get_reason_phrase (query)); + return; +diff --git a/src/gclue-web-source.h b/src/gclue-web-source.h +index 9cc5d31..e466beb 100644 +--- a/src/gclue-web-source.h ++++ b/src/gclue-web-source.h +@@ -73,9 +73,17 @@ struct _GClueWebSourceClass { + SoupMessage * (*create_query) (GClueWebSource *source, + const char **query_data_description, + GError **error); ++ GClueLocation * (*parse_response) (GClueWebSource *source, ++ const char *content, ++ GError **error); + SoupMessage * (*create_submit_query) (GClueWebSource *source, + GClueLocation *location, + GError **error); ++ gboolean (*parse_submit_response) ++ (GClueWebSource *source, ++ const char *content, ++ gboolean status_code, ++ GError **error); + GClueAccuracyLevel (*get_available_accuracy_level) + (GClueWebSource *source, + gboolean network_available); +diff --git a/src/gclue-wifi.c b/src/gclue-wifi.c +index 0649ef0..8efdad5 100644 +--- a/src/gclue-wifi.c ++++ b/src/gclue-wifi.c +@@ -188,6 +188,26 @@ on_scan_done (WPAInterface *object, + gboolean success, + gpointer user_data); + ++static GClueLocation * ++gclue_wifi_parse_response (GClueWebSource *source, ++ const char *content, ++ GError **error) ++{ ++ const char *location_description = ++ gclue_web_source_get_query_data_description (source); ++ ++ return gclue_mozilla_parse_response (content, location_description, error); ++} ++ ++static gboolean ++gclue_wifi_parse_submit_response (GClueWebSource *source, ++ const char *content, ++ gboolean status_code, ++ GError **error) ++{ ++ return gclue_mozilla_parse_submit_response (content, status_code, error); ++} ++ + static void + gclue_wifi_finalize (GObject *gwifi) + { +@@ -223,8 +243,10 @@ gclue_wifi_class_init (GClueWifiClass *klass) + source_class->stop = gclue_wifi_stop; + web_class->refresh_async = gclue_wifi_refresh_async; + web_class->refresh_finish = gclue_wifi_refresh_finish; +- web_class->create_submit_query = gclue_wifi_create_submit_query; + web_class->create_query = gclue_wifi_create_query; ++ web_class->parse_response = gclue_wifi_parse_response; ++ web_class->create_submit_query = gclue_wifi_create_submit_query; ++ web_class->parse_submit_response = gclue_wifi_parse_submit_response; + web_class->get_available_accuracy_level = + gclue_wifi_get_available_accuracy_level; + gwifi_class->finalize = gclue_wifi_finalize; +-- +2.48.1 + + +From 416a6e4fb646d08d5cf3aad054626ac40dcb0c4a Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Mon, 26 Aug 2024 14:39:46 +0300 +Subject: [PATCH] web: Only debug print the beginning of the server response + +The server response may be large, so print only the length of the +response and the first 256 bytes. +--- + src/gclue-web-source.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/gclue-web-source.c b/src/gclue-web-source.c +index 8cd650f..760ebbb 100644 +--- a/src/gclue-web-source.c ++++ b/src/gclue-web-source.c +@@ -138,6 +138,7 @@ refresh_callback (SoupSession *session, + g_autoptr(GError) local_error = NULL; + g_autofree char *contents = NULL; + g_autofree char *str = NULL; ++ g_autofree char *short_contents = NULL; + g_autoptr(GClueLocation) location = NULL; + GUri *uri; + +@@ -160,7 +161,8 @@ refresh_callback (SoupSession *session, + contents = g_strndup (g_bytes_get_data (body, NULL), g_bytes_get_size (body)); + uri = soup_message_get_uri (query); + str = g_uri_to_string (uri); +- g_debug ("Got following response from '%s':\n%s", str, contents); ++ short_contents = g_strndup (contents, 256); ++ g_debug ("Got a response of %ld bytes from '%s' starting with:\n%s", strlen(contents), str, short_contents); + location = GCLUE_WEB_SOURCE_GET_CLASS (web)->parse_response (web, + contents, + &local_error); +-- +2.48.1 + + +From 907db955d0e70952228df49c57adc930141687c0 Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Tue, 27 Aug 2024 19:32:31 +0300 +Subject: [PATCH] web: Ignore received location in query_callback + +Removes a warning about unused variable. +--- + src/gclue-web-source.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/gclue-web-source.c b/src/gclue-web-source.c +index 760ebbb..15af118 100644 +--- a/src/gclue-web-source.c ++++ b/src/gclue-web-source.c +@@ -195,9 +195,11 @@ query_callback (GObject *source_object, + { + GClueWebSource *web = GCLUE_WEB_SOURCE (source_object); + g_autoptr(GError) local_error = NULL; +- g_autoptr(GClueLocation) location = NULL; + +- location = GCLUE_WEB_SOURCE_GET_CLASS (web)->refresh_finish (web, result, &local_error); ++ /* Ignore returned location */ ++ GClueLocation *location = GCLUE_WEB_SOURCE_GET_CLASS (web)->refresh_finish (web, result, &local_error); ++ if (location) ++ g_object_unref (location); + + if (local_error != NULL && + !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { +-- +2.48.1 + + +From d251077a29b23d60c10774497ae88db3a70d25ac Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Tue, 27 Aug 2024 19:36:19 +0300 +Subject: [PATCH] web: If source is not active, postpone refresh to start + +Add a boolean var priv->refresh_needed which is set when the location +URL becomes reachable while the source is not active. + +Add a specialized start() method which performs the refresh, if +refresh_needed is true. + +This fixes a race condition during startup where locate_url_checked_cb +(sometimes) runs before the source is marked active and the refresh +call then errors out. + +Also make some style cleanups. +--- + src/gclue-web-source.c | 47 +++++++++++++++++++++++++++++++++++------- + 1 file changed, 39 insertions(+), 8 deletions(-) + +diff --git a/src/gclue-web-source.c b/src/gclue-web-source.c +index 15af118..8436ce5 100644 +--- a/src/gclue-web-source.c ++++ b/src/gclue-web-source.c +@@ -60,6 +60,7 @@ struct _GClueWebSourcePrivate { + const char *submit_url; + gboolean locate_url_reachable; + gboolean submit_url_reachable; ++ gboolean refresh_needed; + }; + + enum +@@ -272,8 +273,11 @@ locate_url_checked_cb (GObject *source_object, + reachable ? "Enabling locate URL queries" : + "Disabling locate URL queries"); + if (reachable) { +- GCLUE_WEB_SOURCE_GET_CLASS (web)->refresh_async +- (web, NULL, query_callback, NULL); ++ refresh_accuracy_level (web); ++ if (gclue_location_source_get_active (GCLUE_LOCATION_SOURCE (web))) ++ gclue_web_source_refresh (web); ++ else ++ web->priv->refresh_needed = TRUE; /* postpone to start */ + } + } + +@@ -377,6 +381,30 @@ on_connectivity_changed (GObject *gobject, + on_network_changed (NULL, FALSE, user_data); + } + ++static GClueLocationSourceStartResult ++gclue_web_source_start (GClueLocationSource *source) ++{ ++ GClueLocationSourceClass *base_class; ++ GClueWebSource *web; ++ GClueLocationSourceStartResult base_result; ++ ++ g_return_val_if_fail (GCLUE_IS_LOCATION_SOURCE (source), ++ GCLUE_LOCATION_SOURCE_START_RESULT_FAILED); ++ web = GCLUE_WEB_SOURCE (source); ++ ++ base_class = GCLUE_LOCATION_SOURCE_CLASS (gclue_web_source_parent_class); ++ base_result = base_class->start (source); ++ if (base_result != GCLUE_LOCATION_SOURCE_START_RESULT_OK) ++ return base_result; ++ ++ if (web->priv->refresh_needed) { ++ web->priv->refresh_needed = FALSE; ++ gclue_web_source_refresh (web); ++ } ++ ++ return base_result; ++} ++ + static void + gclue_web_source_finalize (GObject *gsource) + { +@@ -502,15 +530,18 @@ gclue_web_source_set_property (GObject *object, + static void + gclue_web_source_class_init (GClueWebSourceClass *klass) + { +- GObjectClass *gsource_class = G_OBJECT_CLASS (klass); ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ GClueLocationSourceClass *source_class = GCLUE_LOCATION_SOURCE_CLASS (klass); + + klass->refresh_async = gclue_web_source_real_refresh_async; + klass->refresh_finish = gclue_web_source_real_refresh_finish; + +- gsource_class->get_property = gclue_web_source_get_property; +- gsource_class->set_property = gclue_web_source_set_property; +- gsource_class->finalize = gclue_web_source_finalize; +- gsource_class->constructed = gclue_web_source_constructed; ++ source_class->start = gclue_web_source_start; ++ ++ object_class->get_property = gclue_web_source_get_property; ++ object_class->set_property = gclue_web_source_set_property; ++ object_class->finalize = gclue_web_source_finalize; ++ object_class->constructed = gclue_web_source_constructed; + + gParamSpecs[PROP_ACCURACY_LEVEL] = g_param_spec_enum ("accuracy-level", + "AccuracyLevel", +@@ -519,7 +550,7 @@ gclue_web_source_class_init (GClueWebSourceClass *klass) + GCLUE_ACCURACY_LEVEL_CITY, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY); +- g_object_class_install_property (gsource_class, ++ g_object_class_install_property (object_class, + PROP_ACCURACY_LEVEL, + gParamSpecs[PROP_ACCURACY_LEVEL]); + } +-- +2.48.1 + + +From 0e5dcfa053c2bf7063820eb43619df21be926645 Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Mon, 26 Aug 2024 21:30:06 +0300 +Subject: [PATCH] Add GClueIp class implementing an ip (AKA GeoIP) source + +This class can contain several method (backend) implementations, only +one of which can be enabled at a time in the configuration. + +New methods only need to implement two functions, one to create a +SoupMessage query and another to parse the response. + +Currently implemented methods are ichnaea, which uses the same API and +URL as the wifi source, and gmaps, which uses the initial location +estimate of Google Maps. +--- + meson.build | 5 +- + meson_options.txt | 3 + + src/gclue-config.c | 42 ++++++- + src/gclue-config.h | 2 + + src/gclue-ip.c | 270 ++++++++++++++++++++++++++++++++++++++++++++ + src/gclue-ip.h | 69 +++++++++++ + src/gclue-locator.c | 11 ++ + src/meson.build | 1 + + 8 files changed, 401 insertions(+), 2 deletions(-) + create mode 100644 src/gclue-ip.c + create mode 100644 src/gclue-ip.h + +diff --git a/meson.build b/meson.build +index 74f7578..bd0003a 100644 +--- a/meson.build ++++ b/meson.build +@@ -38,6 +38,7 @@ conf.set10('GCLUE_USE_CDMA_SOURCE', get_option('cdma-source')) + conf.set10('GCLUE_USE_MODEM_GPS_SOURCE', get_option('modem-gps-source')) + conf.set10('GCLUE_USE_NMEA_SOURCE', get_option('nmea-source')) + conf.set10('GCLUE_USE_STATIC_SOURCE', get_option('static-source')) ++conf.set10('GCLUE_USE_IP_SOURCE', get_option('ip-source')) + conf.set10('GCLUE_USE_COMPASS', get_option('compass')) + + configure_file(output: 'config.h', configuration : conf) +@@ -98,7 +99,8 @@ summary = ''' + Modem GPS source: @10@ + Network NMEA source: @11@ + Static source: @12@ +- Compass: @13@ ++ IP source: @13@ ++ Compass: @14@ + '''.format(gclue_version, + get_option('prefix'), + cc.get_id(), +@@ -112,5 +114,6 @@ summary = ''' + get_option('modem-gps-source'), + get_option('nmea-source'), + get_option('static-source'), ++ get_option('ip-source'), + get_option('compass')) + message(summary) +diff --git a/meson_options.txt b/meson_options.txt +index 76825d0..228d5a8 100644 +--- a/meson_options.txt ++++ b/meson_options.txt +@@ -28,6 +28,9 @@ option('nmea-source', + option('static-source', + type: 'boolean', value: true, + description: 'Enable static source (geolocation file)') ++option('ip-source', ++ type: 'boolean', value: true, ++ description: 'Enable ip source (GeoIP)') + option('compass', + type: 'boolean', value: true, + description: 'Enable setting heading from net.hadess.SensorProxy compass') +diff --git a/src/gclue-config.c b/src/gclue-config.c +index 0691f47..71de78b 100644 +--- a/src/gclue-config.c ++++ b/src/gclue-config.c +@@ -48,9 +48,11 @@ struct _GClueConfigPrivate + gboolean enable_wifi_source; + gboolean enable_compass; + gboolean enable_static_source; ++ gboolean enable_ip_source; + char *wifi_submit_url; + char *wifi_submit_nick; + char *nmea_socket; ++ char *ip_method; + + GList *app_configs; + }; +@@ -90,6 +92,7 @@ gclue_config_finalize (GObject *object) + g_clear_pointer (&priv->wifi_submit_url, g_free); + g_clear_pointer (&priv->wifi_submit_nick, g_free); + g_clear_pointer (&priv->nmea_socket, g_free); ++ g_clear_pointer (&priv->ip_method, g_free); + + g_list_foreach (priv->app_configs, (GFunc) app_config_free, NULL); + +@@ -205,7 +208,7 @@ load_app_configs (GClueConfig *config) + { + const char *known_groups[] = { "agent", "wifi", "3g", "cdma", + "modem-gps", "network-nmea", "compass", +- "static-source", NULL }; ++ "static-source", "ip", NULL }; + GClueConfigPrivate *priv = config->priv; + gsize num_groups = 0, i; + g_auto(GStrv) groups = NULL; +@@ -405,6 +408,18 @@ load_static_source_config (GClueConfig *config) + &config->priv->enable_static_source); + } + ++static void ++load_ip_source_config (GClueConfig *config) ++{ ++ GClueConfigPrivate *priv = config->priv; ++ ++ load_enable_source (config, "ip", GCLUE_USE_IP_SOURCE, ++ &priv->enable_ip_source); ++ ++ load_string_value (config, "ip", "method", &priv->ip_method); ++ ++} ++ + static void + load_config_file (GClueConfig *config, const char *path) { + g_autoptr(GError) error = NULL; +@@ -429,6 +444,7 @@ load_config_file (GClueConfig *config, const char *path) { + load_network_nmea_config (config); + load_compass_config (config); + load_static_source_config (config); ++ load_ip_source_config (config); + } + + static void +@@ -529,6 +545,10 @@ gclue_config_print (GClueConfig *config) + string_or_none (priv->wifi_submit_nick)); + g_debug ("Static source: %s", + enabled_disabled (priv->enable_static_source)); ++ g_debug ("IP source: %s", ++ enabled_disabled (priv->enable_ip_source)); ++ g_debug ("\tIP method: %s", ++ string_or_none (priv->ip_method)); + g_debug ("Compass: %s", + enabled_disabled (priv->enable_compass)); + g_debug ("Application configs:"); +@@ -566,6 +586,7 @@ gclue_config_init (GClueConfig *config) + priv->enable_wifi_source = TRUE; + priv->enable_compass = TRUE; + priv->enable_static_source = TRUE; ++ priv->enable_ip_source = TRUE; + + /* Default strings */ + priv->wifi_url = g_strdup (DEFAULT_WIFI_URL); +@@ -622,6 +643,13 @@ out: + "disabling WiFi/3G submissions"); + priv->wifi_submit = FALSE; + } ++ if (priv->enable_ip_source && (!string_present (priv->ip_method) || ++ (g_strcmp0 (priv->ip_method, "ichnaea") != 0 && ++ g_strcmp0 (priv->ip_method, "gmaps") != 0))) { ++ g_warning ("Unknown IP source method '%s', disabling source", priv->ip_method); ++ priv->enable_ip_source = FALSE; ++ g_clear_pointer (&priv->ip_method, g_free); ++ } + gclue_config_print (config); + } + +@@ -818,3 +846,15 @@ gclue_config_get_enable_static_source (GClueConfig *config) + { + return config->priv->enable_static_source; + } ++ ++gboolean ++gclue_config_get_enable_ip_source (GClueConfig *config) ++{ ++ return config->priv->enable_ip_source; ++} ++ ++const char * ++gclue_config_get_ip_method (GClueConfig *config) ++{ ++ return config->priv->ip_method; ++} +diff --git a/src/gclue-config.h b/src/gclue-config.h +index db66f86..78e05e4 100644 +--- a/src/gclue-config.h ++++ b/src/gclue-config.h +@@ -85,6 +85,7 @@ void gclue_config_set_wifi_submit_nick (GClueConfig *config + gboolean gclue_config_get_wifi_submit_data (GClueConfig *config); + void gclue_config_set_wifi_submit_data (GClueConfig *config, + gboolean submit); ++const char * gclue_config_get_ip_method (GClueConfig *config); + gboolean gclue_config_get_enable_wifi_source (GClueConfig *config); + gboolean gclue_config_get_enable_3g_source (GClueConfig *config); + gboolean gclue_config_get_enable_cdma_source (GClueConfig *config); +@@ -94,6 +95,7 @@ gboolean gclue_config_get_enable_nmea_source (GClueConfig *config + gboolean gclue_config_get_enable_compass (GClueConfig *config); + gboolean gclue_config_get_enable_static_source + (GClueConfig *config); ++gboolean gclue_config_get_enable_ip_source (GClueConfig *config); + + G_END_DECLS + +diff --git a/src/gclue-ip.c b/src/gclue-ip.c +new file mode 100644 +index 0000000..4d018c4 +--- /dev/null ++++ b/src/gclue-ip.c +@@ -0,0 +1,270 @@ ++/* vim: set et ts=8 sw=8: */ ++/* ++ * Copyright 2024 Teemu Ikonen ++ * ++ * Geoclue 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 2 of the License, or (at your option) ++ * any later version. ++ * ++ * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ * Authors: Teemu Ikonen ++ */ ++ ++#include ++#include ++#include ++#include ++#include "config.h" ++#include "gclue-ip.h" ++#include "gclue-config.h" ++#include "gclue-error.h" ++#include "gclue-mozilla.h" ++ ++/** ++ * SECTION:gclue-ip ++ * @short_description: IP address based geolocation ++ * @include: gclue-glib/gclue-ip.h ++ * ++ * Contains functions to determine the geolocation based on the IP address. ++ **/ ++ ++struct _GClueIpPrivate { ++ GCancellable *cancellable; ++ ++ /* Ichnaea */ ++ GClueMozilla *mozilla; ++ /* GMaps */ ++ GRegex *gregex; ++}; ++ ++G_DEFINE_TYPE_WITH_CODE (GClueIp, ++ gclue_ip, ++ GCLUE_TYPE_WEB_SOURCE, ++ G_ADD_PRIVATE (GClueIp)) ++ ++/* Ichnaea method */ ++ ++static SoupMessage * ++ichnaea_create_query (GClueWebSource *source, ++ const char **query_data_description, ++ GError **error) ++{ ++ GClueIp *ip = GCLUE_IP (source); ++ ++ return gclue_mozilla_create_query (ip->priv->mozilla, TRUE, TRUE, ++ query_data_description, error); ++} ++ ++static GClueLocation * ++ichnaea_parse_response (GClueWebSource *source, ++ const char *content, ++ GError **error) ++{ ++ const char *description = gclue_web_source_get_query_data_description (source); ++ ++ return gclue_mozilla_parse_response (content, description, error); ++} ++ ++/* GMaps method */ ++ ++#define GMAPS_URL "https://www.google.com/maps" ++#define GMAPS_SCALE 1e7 /* meters */ ++ ++static SoupMessage * ++gmaps_create_query (GClueWebSource *source, ++ const char **query_data_description, ++ GError **error) ++{ ++ g_autoptr(SoupMessage) query = NULL; ++ ++ query = soup_message_new ("GET", GMAPS_URL); ++ if (query_data_description) { ++ *query_data_description = "GMaps IP"; ++ } ++ ++ return g_steal_pointer (&query); ++} ++ ++static double ++round_to_1fig (double x) ++{ ++ int zeros, base; ++ ++ zeros = (int) floor (log10 (x)); ++ base = pow (10, zeros); ++ return round (x / base) * base; ++} ++ ++static GClueLocation * ++gmaps_parse_response (GClueWebSource *source, ++ const char *response, ++ GError **error) ++{ ++ GClueIp *ip = GCLUE_IP (source); ++ g_autoptr(GMatchInfo) match_info = NULL; ++ g_autofree char *locstring = NULL; ++ double latitude, longitude, accuracy; ++ guint64 zoom; ++ char *lat_end, *lon_end, *zoom_end; ++ GClueLocation *location; ++ ++ g_regex_match (ip->priv->gregex, response, 0, &match_info); ++ if (!g_match_info_matches (match_info)) { ++ g_warning ("No location found from GMaps response"); ++ return NULL; ++ } ++ locstring = g_match_info_fetch (match_info, 0); ++ g_debug ("GMaps location string: %s", locstring); ++ latitude = g_ascii_strtod (locstring + 7, &lat_end); ++ longitude = g_ascii_strtod (lat_end + 3, &lon_end); ++ zoom = g_ascii_strtoull (lon_end + 10, &zoom_end, 10); ++ accuracy = round_to_1fig (zoom >= 1 ? GMAPS_SCALE / (1 << (zoom - 1)) : ++ GMAPS_SCALE); ++ g_debug ("Parsed GMaps values lat=%.8f, lon=%.8f, zoom=%lu", ++ latitude, longitude, zoom); ++ if (latitude <= -180.0 || latitude > 180.0 || ++ longitude > 90.0 || longitude < -90.0 || ++ accuracy > GMAPS_SCALE || accuracy < 1.0) { ++ g_warning ("GMaps coordinates are invalid: lat=%.8f, lon=%.8f, acc=%f", ++ latitude, longitude, accuracy); ++ return NULL; ++ } ++ location = gclue_location_new (latitude, longitude, accuracy, ++ gclue_web_source_get_query_data_description(source)); ++ ++ return location; ++} ++ ++/* GClueIp common */ ++ ++static void ++gclue_ip_finalize (GObject *gip) ++{ ++ GClueIp *ip = (GClueIp *) gip; ++ ++ G_OBJECT_CLASS (gclue_ip_parent_class)->finalize (gip); ++ ++ g_cancellable_cancel (ip->priv->cancellable); ++ ++ g_clear_object (&ip->priv->cancellable); ++ g_clear_object (&ip->priv->mozilla); ++ g_clear_pointer (&ip->priv->gregex, g_regex_unref); ++} ++ ++static GClueLocationSourceStartResult ++gclue_ip_start (GClueLocationSource *source) ++{ ++ GClueLocationSourceClass *base_class; ++ GClueLocationSourceStartResult base_result; ++ ++ g_return_val_if_fail (GCLUE_IS_IP (source), ++ GCLUE_LOCATION_SOURCE_START_RESULT_FAILED); ++ ++ base_class = GCLUE_LOCATION_SOURCE_CLASS (gclue_ip_parent_class); ++ base_result = base_class->start (source); ++ if (base_result == GCLUE_LOCATION_SOURCE_START_RESULT_OK ++ && gclue_location_source_get_location (source) != NULL) { ++ g_debug ("Notifying old IP location"); ++ g_object_notify (G_OBJECT (source), "location"); ++ } ++ ++ return base_result; ++} ++ ++static GClueAccuracyLevel ++gclue_ip_get_available_accuracy_level (GClueWebSource *source, ++ gboolean net_available) ++{ ++ if (!net_available) ++ return GCLUE_ACCURACY_LEVEL_NONE; ++ else ++ return GCLUE_ACCURACY_LEVEL_CITY; ++} ++ ++static void ++gclue_ip_class_init (GClueIpClass *klass) ++{ ++ GClueWebSourceClass *web_class = GCLUE_WEB_SOURCE_CLASS (klass); ++ GClueLocationSourceClass *source_class = GCLUE_LOCATION_SOURCE_CLASS (klass); ++ GObjectClass *ip_class = G_OBJECT_CLASS (klass); ++ GClueConfig *config = gclue_config_get_singleton (); ++ const char *method; ++ ++ source_class->start = gclue_ip_start; ++ ++ web_class->get_available_accuracy_level = gclue_ip_get_available_accuracy_level; ++ method = gclue_config_get_ip_method (config); ++ if (g_strcmp0 (method, "ichnaea") == 0) { ++ web_class->create_query = ichnaea_create_query; ++ web_class->parse_response = ichnaea_parse_response; ++ } else if (g_strcmp0 (method, "gmaps") == 0) { ++ web_class->create_query = gmaps_create_query; ++ web_class->parse_response = gmaps_parse_response; ++ } else { ++ g_error ("Unknown IP method '%s'", method); ++ } ++ ++ ip_class->finalize = gclue_ip_finalize; ++} ++ ++static void ++gclue_ip_init (GClueIp *ip) ++{ ++ GClueWebSource *web_source = GCLUE_WEB_SOURCE (ip); ++ GClueConfig *config = gclue_config_get_singleton (); ++ const char *method; ++ ++ ip->priv = gclue_ip_get_instance_private (ip); ++ ++ ip->priv->cancellable = g_cancellable_new (); ++ ++ method = gclue_config_get_ip_method (config); ++ if (g_strcmp0 (method, "ichnaea") == 0) { ++ ip->priv->mozilla = gclue_mozilla_get_singleton (); ++ gclue_web_source_set_locate_url ++ (web_source, gclue_mozilla_get_locate_url (ip->priv->mozilla)); ++ } else if (g_strcmp0 (method, "gmaps") == 0) { ++ ip->priv->gregex = g_regex_new ++ ("center=[0-9\\.]*%2C[0-9\\.]*&zoom=[0-9]*&", ++ G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, NULL); ++ gclue_web_source_set_locate_url (web_source, GMAPS_URL); ++ } else { ++ g_error ("Unknown IP method '%s'", method); ++ } ++} ++ ++/** ++ * gclue_ip_get_singleton: ++ * ++ * Get the #GClueIp singleton. ++ * ++ * Returns: (transfer full): a new ref to #GClueIp. Use g_object_unref() ++ * when done. ++ **/ ++GClueIp * ++gclue_ip_get_singleton (void) ++{ ++ static GClueIp *ip = NULL; ++ ++ if (ip == NULL) { ++ ip = g_object_new (GCLUE_TYPE_IP, ++ "accuracy-level", GCLUE_ACCURACY_LEVEL_CITY, ++ "compute-movement", FALSE, ++ NULL); ++ g_object_add_weak_pointer (G_OBJECT (ip), ++ (gpointer) &ip); ++ } else { ++ g_object_ref (ip); ++ } ++ ++ return ip; ++} +diff --git a/src/gclue-ip.h b/src/gclue-ip.h +new file mode 100644 +index 0000000..04fa2fb +--- /dev/null ++++ b/src/gclue-ip.h +@@ -0,0 +1,69 @@ ++/* vim: set et ts=8 sw=8: */ ++/* ++ * Copyright 2024 Teemu Ikonen ++ * ++ * Geoclue 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 2 of the License, or (at your option) ++ * any later version. ++ * ++ * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ * Authors: Teemu Ikonen ++ */ ++ ++#ifndef GCLUE_IP_H ++#define GCLUE_IP_H ++ ++#include ++#include ++#include "gclue-web-source.h" ++ ++G_BEGIN_DECLS ++ ++GType gclue_ip_get_type (void) G_GNUC_CONST; ++ ++#define GCLUE_TYPE_IP (gclue_ip_get_type ()) ++#define GCLUE_IP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_IP, GClueIp)) ++#define GCLUE_IS_IP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCLUE_TYPE_IP)) ++#define GCLUE_IP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCLUE_TYPE_IP, GClueIpClass)) ++#define GCLUE_IS_IP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCLUE_TYPE_IP)) ++#define GCLUE_IP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCLUE_TYPE_IP, GClueIpClass)) ++ ++/** ++ * GClueIp: ++ * ++ * All the fields in the #GClueIp structure are private and should never be accessed directly. ++**/ ++typedef struct _GClueIp GClueIp; ++typedef struct _GClueIpClass GClueIpClass; ++typedef struct _GClueIpPrivate GClueIpPrivate; ++ ++struct _GClueIp { ++ /* */ ++ GClueWebSource parent_instance; ++ GClueIpPrivate *priv; ++}; ++ ++/** ++ * GClueIpClass: ++ * ++ * All the fields in the #GClueIpClass structure are private and should never be accessed directly. ++**/ ++struct _GClueIpClass { ++ /* */ ++ GClueWebSourceClass parent_class; ++}; ++ ++GClueIp * gclue_ip_get_singleton (void); ++ ++G_END_DECLS ++ ++#endif /* GCLUE_IP_H */ +diff --git a/src/gclue-locator.c b/src/gclue-locator.c +index d6aa347..c8a9dda 100644 +--- a/src/gclue-locator.c ++++ b/src/gclue-locator.c +@@ -54,6 +54,10 @@ + #include "gclue-static-source.h" + #endif + ++#if GCLUE_USE_IP_SOURCE ++#include "gclue-ip.h" ++#endif ++ + /* This class is like a master location source that hides all individual + * location sources from rest of the code + */ +@@ -475,6 +479,13 @@ gclue_locator_constructed (GObject *object) + static_source); + } + #endif ++#if GCLUE_USE_IP_SOURCE ++ if (gclue_config_get_enable_ip_source (gconfig)) { ++ GClueIp *source = gclue_ip_get_singleton (); ++ locator->priv->sources = g_list_append (locator->priv->sources, ++ source); ++ } ++#endif + + if (locator->priv->sources == NULL) { + g_warning ("No sources enabled in configuration, " +diff --git a/src/meson.build b/src/meson.build +index b5175f8..451edd6 100644 +--- a/src/meson.build ++++ b/src/meson.build +@@ -26,6 +26,7 @@ sources += [ 'gclue-main.c', + 'gclue-service-location.h', 'gclue-service-location.c', + 'gclue-static-source.c', 'gclue-static-source.h', + 'gclue-web-source.c', 'gclue-web-source.h', ++ 'gclue-ip.h', 'gclue-ip.c', + 'gclue-wifi.h', 'gclue-wifi.c', + 'gclue-mozilla.h', 'gclue-mozilla.c', + 'gclue-min-uint.h', 'gclue-min-uint.c', +-- +2.48.1 + + +From 749fb6b846ebd65245a78e831e8bccc2e30c13e7 Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Thu, 29 Aug 2024 13:53:57 +0300 +Subject: [PATCH] data: geoclue.conf.in: Add configuration for the ip source + +--- + data/geoclue.conf.in | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/data/geoclue.conf.in b/data/geoclue.conf.in +index c0e876e..c8bc311 100644 +--- a/data/geoclue.conf.in ++++ b/data/geoclue.conf.in +@@ -12,6 +12,17 @@ + # separated by a ';'. + whitelist=@demo_agent@gnome-shell;io.elementary.desktop.agent-geoclue2;sm.puri.Phosh;lipstick + ++# IP source configuration options ++[ip] ++ ++# Enable the GeoIP source ++enable=true ++ ++# Method (backend) to use for IP location. Currently implemented are: ++# 'ichnaea': Use the Ichnaea (MLS) API with the URL from the wifi source. ++# 'gmaps': Use the location determined by Google Maps. ++method=ichnaea ++ + # Network NMEA source configuration options + [network-nmea] + +-- +2.48.1 + + +From a82a906abcf909b5b80f5012b82ad9ec685c5ef4 Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Thu, 5 Dec 2024 12:42:05 +0200 +Subject: [PATCH] .editorconfig: Add man page to 'max_line_length = 80' section + +--- + .editorconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/.editorconfig b/.editorconfig +index 56ff6a0..d203c8b 100644 +--- a/.editorconfig ++++ b/.editorconfig +@@ -20,5 +20,5 @@ indent_style = space + indent_size = 4 + indent_style = space + +-[*.md] ++[*.{md,5.in}] + max_line_length = 80 +-- +2.48.1 + + +From 442973f15762e64ddf43b9737b44d9be4b0ee2da Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Thu, 5 Dec 2024 12:43:42 +0200 +Subject: [PATCH] data: Make man page lines (mostly) under 80 chars + +--- + data/geoclue.5.in | 28 ++++++++++++++++++---------- + 1 file changed, 18 insertions(+), 10 deletions(-) + +diff --git a/data/geoclue.5.in b/data/geoclue.5.in +index 1f21995..cca68a5 100644 +--- a/data/geoclue.5.in ++++ b/data/geoclue.5.in +@@ -17,10 +17,9 @@ order. Thus, a configuration file '90-config.conf' will overwrite parameters + specified in another configuration file '50-config.conf' in the conf.d + directory. + .PP +-All configurations settings below are mandatory and the defaults are +-what you see before you edit them in geoclue.conf. If you want to keep the default +-values around, copy and comment out the appropriate line(s) before +-changing them. ++All configurations settings below are mandatory and the defaults are what you ++see before you edit them in geoclue.conf. If you want to keep the default values ++around, copy and comment out the appropriate line(s) before changing them. + .PP + Missing 'enable' key for a particular source in the main configuration file + causes that source to be enabled by default. Adding 'enable' key setting +@@ -99,7 +98,8 @@ URL to submission API of Mozilla Location Service + .IP + .B submission-nick=geoclue + .br +-A nickname to submit network data with. If empty, omitted from the submission. Otherwise, must be 2 to 32 characters long. Defaults to "geoclue". ++A nickname to submit network data with. If empty, omitted from the submission. ++Otherwise, must be 2 to 32 characters long. Defaults to "geoclue". + .br + .IP \fB[compass] + .br +@@ -113,7 +113,11 @@ Enable Compass + .br + Static source configuration options. + .br +-This source reads location from "geolocation" file in @sysconfdir@. While this file is constantly monitored for changes during geoclue operation, and the reported static location is updated accordingly, this source isn't meant for inputting a dynamically changing location to geoclue (please use the Network NMEA source for that). ++This source reads location from "geolocation" file in @sysconfdir@. While this ++file is constantly monitored for changes during geoclue operation, and the ++reported static location is updated accordingly, this source isn't meant for ++inputting a dynamically changing location to geoclue (please use the Network ++NMEA source for that). + .IP + .B \fBenable=true + .br +@@ -205,7 +209,8 @@ users= + .br + .SH STATIC LOCATION FILE + .SS Basic format: +-The static location file in @sysconfdir@ (used by the static source) is a text file consisting of the following: ++The static location file in @sysconfdir@ (used by the static source) is a text ++file consisting of the following: + .nr step 1 1 + .IP \n[step] + Latitude (floating point number; positive values mean north, negative south) +@@ -220,7 +225,8 @@ Accuracy radius (floating point number; in meters) + These values need to be separated by newline characters. + .SS Additional format information: + .IP \[bu] +-The '\[sh]' character starts a comment, which continues until the end of the current line. ++The '\[sh]' character starts a comment, which continues until the end of the ++current line. + .IP \[bu] + Leading and trailing white-space on each line is ignored. + .IP \[bu] +@@ -235,14 +241,16 @@ Empty lines (or containing just white-space or a comment) are ignored. + 1.83 # accuracy radius (the diameter of the torch is 12 feet) + .EE + .SS Notes: +-For extra security, the static location file can be made readable just by the geoclue user: ++For extra security, the static location file can be made readable just by the ++geoclue user: + .EX + # chown @dbus_srv_user@ @sysconfdir@/geolocation + # chmod 600 @sysconfdir@/geolocation + .EE + .br + .SH CLIENT LIST +-Sending SIGUSR1 to a running geoclue process prints the current list of clients to the log. ++Sending SIGUSR1 to a running geoclue process prints the current list of clients ++to the log. + .br + .SH AUTHOR + .na +-- +2.48.1 + + +From 0cf7050dac529c0a4327d4f8b87b4e3dc38cd528 Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Thu, 5 Dec 2024 12:34:37 +0200 +Subject: [PATCH] data: Add a source configuration section to the man page + +--- + data/geoclue.5.in | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/data/geoclue.5.in b/data/geoclue.5.in +index cca68a5..81d8efb 100644 +--- a/data/geoclue.5.in ++++ b/data/geoclue.5.in +@@ -34,6 +34,7 @@ separated by a ';'. + .IP + .B whitelist=geoclue-demo-agent;gnome-shell;io.elementary.desktop.agent-geoclue2 + .br ++.SH LOCATION SOURCE CONFIGURATION OPTIONS + .IP \fB[network-nmea] + .br + Network NMEA source configuration options +-- +2.48.1 + + +From 68d041871ffb9af458cf0dd223e5484f648bbae4 Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Thu, 5 Dec 2024 14:41:04 +0200 +Subject: [PATCH] data: Improve the man page for 3g, wifi and static sources + +Remove references to Mozilla Location Service. +--- + data/geoclue.5.in | 42 ++++++++++++++++++++++++++---------------- + 1 file changed, 26 insertions(+), 16 deletions(-) + +diff --git a/data/geoclue.5.in b/data/geoclue.5.in +index 81d8efb..8c21728 100644 +--- a/data/geoclue.5.in ++++ b/data/geoclue.5.in +@@ -55,7 +55,8 @@ If not set, unix socket will not be used. + .IP + .B \fBenable=true + .br +-Enable 3G source ++Enable 3G source. The 3G source uses the wireless geolocation service URL ++defined in the "wifi" section. + .br + .IP \fB[cdma] + .br +@@ -81,25 +82,34 @@ WiFi source configuration options + .br + Enable WiFi source + .IP +-.B url=\fIhttps://location.services.mozilla.com/v1/geolocate?key=YOUR_KEY ++.B url=\fIhttps://example.com/v1/geolocate?key=YOUR_KEY + .br +-URL to the WiFi geolocation service. If not set, defaults to Mozilla's +-Location Service with a hardcoded key. To use a custom key, uncomment this URL +-while changing YOUR_KEY to your MLS API key. ++URL to wireless geolocation service compatible with the Ichnaea API ++(https://ichnaea.readthedocs.io/en/latest/api/geolocate.html). If not set, ++defaults to an URL set in the build configuration. If an URL is not set here or ++in the build configuration, the wifi and 3g sources will be disabled. An API key ++can be set with the "key" URL parameter. + .IP + .B submit-data=false +-Submit data to Mozilla Location Service + .br +-If set to true, geoclue will automatically submit network data to Mozilla +-each time it gets a GPS lock. ++Submit data to a wireless geolocation service. ++.br ++If set to true, geoclue will automatically submit network data to a wireless ++geolocation service each time it gets a GPS lock. Currently, only Modem-GPS or ++Network NMEA sources are supported as providers of a location to submit (one at ++a time). If Modem-GPS source is enabled above it will be the exclusive provider ++(regardless whether the system is actually equipped with such modem), otherwise ++Network NMEA source will be considered. + .IP +-.B submission-url=\fIhttps://location.services.mozilla.com/v2/geosubmit?key=YOUR_KEY ++.B submission-url=\fIhttps://example.com/v2/geosubmit?key=YOUR_KEY + .br +-URL to submission API of Mozilla Location Service ++URL to submit data to a wireless geolocation service with an Ichnaea compatible ++API (https://ichnaea.readthedocs.io/en/latest/api/geosubmit2.html). + .IP + .B submission-nick=geoclue + .br +-A nickname to submit network data with. If empty, omitted from the submission. ++A nickname to submit network data with. Sets an "X-Nickname" HTTP header to the ++submit request. If set to an empty string, omitted from the submission. + Otherwise, must be 2 to 32 characters long. Defaults to "geoclue". + .br + .IP \fB[compass] +@@ -114,11 +124,11 @@ Enable Compass + .br + Static source configuration options. + .br +-This source reads location from "geolocation" file in @sysconfdir@. While this +-file is constantly monitored for changes during geoclue operation, and the +-reported static location is updated accordingly, this source isn't meant for +-inputting a dynamically changing location to geoclue (please use the Network +-NMEA source for that). ++This source reads location from "geolocation" file in @sysconfdir@. See "STATIC ++LOCATION FILE" below for the format of this file. While this file is constantly ++monitored for changes during geoclue operation, and the reported static location ++is updated accordingly, this source isn't meant for inputting a dynamically ++changing location to geoclue (please use the Network NMEA source for that). + .IP + .B \fBenable=true + .br +-- +2.48.1 + + +From bfda8ddd333c9288c5418a659578497054488fd0 Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Thu, 5 Dec 2024 14:53:33 +0200 +Subject: [PATCH] data: Document IP source configuration in the man page + +--- + data/geoclue.5.in | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/data/geoclue.5.in b/data/geoclue.5.in +index 8c21728..ca58f0d 100644 +--- a/data/geoclue.5.in ++++ b/data/geoclue.5.in +@@ -35,6 +35,23 @@ separated by a ';'. + .B whitelist=geoclue-demo-agent;gnome-shell;io.elementary.desktop.agent-geoclue2 + .br + .SH LOCATION SOURCE CONFIGURATION OPTIONS ++.IP \fB[ip] ++.br ++IP source configuration options ++.IP ++.B \fBenable=true ++.br ++Enable the GeoIP source ++.br ++.IP ++.B \fBmethod=gmaps ++.br ++Method (backend) to use for IP location. Currently implemented are: ++.br ++"ichnaea": Use the Ichnaea API with the URL from the wifi source. ++.br ++"gmaps": Use the location determined by Google Maps. ++.br + .IP \fB[network-nmea] + .br + Network NMEA source configuration options +-- +2.48.1 + + +From 46c2873212e01a3ce18ef9d01eab9097eb7cebc6 Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Mon, 26 Aug 2024 15:35:08 +0300 +Subject: [PATCH] locator: Add wifi to sources only if it is enabled + +That is, do not use the wifi source for GeoIP location. +--- + src/gclue-locator.c | 12 +----------- + 1 file changed, 1 insertion(+), 11 deletions(-) + +diff --git a/src/gclue-locator.c b/src/gclue-locator.c +index c8a9dda..f7a470a 100644 +--- a/src/gclue-locator.c ++++ b/src/gclue-locator.c +@@ -432,18 +432,8 @@ gclue_locator_constructed (GObject *object) + } + #endif + #if GCLUE_USE_WIFI_SOURCE +- GClueWifi *wifi = NULL; + if (gclue_config_get_enable_wifi_source (gconfig)) { +- wifi = gclue_wifi_get_singleton (locator->priv->accuracy_level); +- } else { +- if (gclue_config_get_enable_static_source (gconfig)) { +- g_debug ("Disabling GeoIP-only source since static source is enabled"); +- } else { +- /* City-level accuracy will give us GeoIP-only source */ +- wifi = gclue_wifi_get_singleton (GCLUE_ACCURACY_LEVEL_CITY); +- } +- } +- if (wifi) { ++ GClueWifi *wifi = gclue_wifi_get_singleton (locator->priv->accuracy_level); + locator->priv->sources = g_list_append (locator->priv->sources, + wifi); + } +-- +2.48.1 + + +From ed19098754f72164df460a5c216c81c1e5e2546e Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Sun, 5 Jan 2025 20:50:20 +0200 +Subject: [PATCH] wifi: Remove the IP-only wifi source + +Leave the scrambled wifi source for below street-level accuracy and +the non-scrambled source for higher accuracy levels. + +The wifi source is now always enabled in config when it's created, so +remove the config checks. +--- + src/gclue-wifi.c | 27 ++++----------------------- + 1 file changed, 4 insertions(+), 23 deletions(-) + +diff --git a/src/gclue-wifi.c b/src/gclue-wifi.c +index 8efdad5..62ae1b1 100644 +--- a/src/gclue-wifi.c ++++ b/src/gclue-wifi.c +@@ -22,7 +22,6 @@ + #include + #include + #include +-#include + #include "gclue-wifi.h" + #include "gclue-3g.h" + #include "gclue-config.h" +@@ -1028,13 +1027,6 @@ gclue_wifi_constructed (GObject *object) + + G_OBJECT_CLASS (gclue_wifi_parent_class)->constructed (object); + +- if (get_accuracy_level (wifi) == GCLUE_ACCURACY_LEVEL_CITY) { +- GClueConfig *config = gclue_config_get_singleton (); +- +- if (!gclue_config_get_enable_wifi_source (config)) +- goto refresh_n_exit; +- } +- + /* FIXME: We should be using async variant */ + priv->supplicant = wpa_supplicant_proxy_new_for_bus_sync + (G_BUS_TYPE_SYSTEM, +@@ -1080,7 +1072,7 @@ on_wifi_destroyed (gpointer data, + } + + /** +- * gclue_wifi_new: ++ * gclue_wifi_get_singleton: + * + * Get the #GClueWifi singleton, for the specified max accuracy level @level. + * +@@ -1090,29 +1082,18 @@ on_wifi_destroyed (gpointer data, + GClueWifi * + gclue_wifi_get_singleton (GClueAccuracyLevel level) + { +- static GClueWifi *wifi[] = { NULL, NULL, NULL }; ++ static GClueWifi *wifi[] = { NULL, NULL }; + guint i; +- GClueConfig *config = gclue_config_get_singleton (); +- gboolean wifi_enabled; + gboolean scramble_location = FALSE; + gboolean compute_movement = FALSE; + + g_return_val_if_fail (level >= GCLUE_ACCURACY_LEVEL_CITY, NULL); + +- wifi_enabled = gclue_config_get_enable_wifi_source (config); +- if (level == GCLUE_ACCURACY_LEVEL_CITY) { ++ if (level <= GCLUE_ACCURACY_LEVEL_NEIGHBORHOOD) { + i = 0; +- if (wifi_enabled) +- scramble_location = TRUE; +- } else if (level == GCLUE_ACCURACY_LEVEL_NEIGHBORHOOD) { +- g_return_val_if_fail (wifi_enabled, NULL); +- +- i = 1; + scramble_location = TRUE; + } else { +- g_return_val_if_fail (wifi_enabled, NULL); +- +- i = 2; ++ i = 1; + compute_movement = TRUE; + } + +-- +2.48.1 + + +From 95e89d0cade9954f40f0527ac03a7dc3217cb1db Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Fri, 17 Jan 2025 20:06:31 +0200 +Subject: [PATCH] web-source: Refresh location on network change + +Use a small timeout value to ensure consecutive network changes do not +trigger more than one refresh. +--- + src/gclue-web-source.c | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +diff --git a/src/gclue-web-source.c b/src/gclue-web-source.c +index 8436ce5..7219269 100644 +--- a/src/gclue-web-source.c ++++ b/src/gclue-web-source.c +@@ -242,6 +242,9 @@ get_internet_available (void) + G_NETWORK_CONNECTIVITY_FULL; + } + ++/* This should be equal to WIFI_SCAN_TIMEOUT_HIGH_ACCURACY in gclue-wifi.c */ ++#define WEB_LOCATION_TIMEOUT 10 ++ + static void + locate_url_checked_cb (GObject *source_object, + GAsyncResult *result, +@@ -249,6 +252,7 @@ locate_url_checked_cb (GObject *source_object, + { + GNetworkMonitor *mon = G_NETWORK_MONITOR (source_object); + GClueWebSource *web; ++ GClueLocation *current_location; + gboolean reachable, last_reachable; + g_autoptr(GError) error = NULL; + +@@ -266,13 +270,18 @@ locate_url_checked_cb (GObject *source_object, + web = GCLUE_WEB_SOURCE (user_data); + last_reachable = web->priv->locate_url_reachable; + web->priv->locate_url_reachable = reachable; +- if (last_reachable == reachable) +- return; /* We already reacted to network change */ ++ if (last_reachable != reachable) { ++ g_debug ("Network changed: %s", ++ reachable ? "Enabling locate URL queries" : ++ "Disabling locate URL queries"); ++ } ++ if (!reachable) ++ return; + +- g_debug ("Network changed: %s", +- reachable ? "Enabling locate URL queries" : +- "Disabling locate URL queries"); +- if (reachable) { ++ current_location = gclue_location_source_get_location (GCLUE_LOCATION_SOURCE (web)); ++ if (!current_location || (g_get_real_time () / G_USEC_PER_SEC) ++ > (gclue_location_get_timestamp (current_location) + WEB_LOCATION_TIMEOUT)) { ++ g_debug ("Network changed: Refreshing"); + refresh_accuracy_level (web); + if (gclue_location_source_get_active (GCLUE_LOCATION_SOURCE (web))) + gclue_web_source_refresh (web); +-- +2.48.1 + + +From 9d4d99b4d7de499e5ec7e47bdc1ec0399ed942ad Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Sun, 19 Jan 2025 21:22:41 +0200 +Subject: [PATCH] web-source: Promote refresh_accuracy_level() to a method + +Rename refresh_accuracy_level() to +gclue_web_source_refresh_available_accuracy_level() and add it to the +header file as a web-source method. +--- + src/gclue-web-source.c | 11 ++++------- + src/gclue-web-source.h | 1 + + 2 files changed, 5 insertions(+), 7 deletions(-) + +diff --git a/src/gclue-web-source.c b/src/gclue-web-source.c +index 7219269..d7e4866 100644 +--- a/src/gclue-web-source.c ++++ b/src/gclue-web-source.c +@@ -38,9 +38,6 @@ + * Baseclass for all sources that solely use a web resource for geolocation. + **/ + +-static void +-refresh_accuracy_level (GClueWebSource *web); +- + struct _GClueWebSourcePrivate { + GCancellable *cancellable; + +@@ -92,7 +89,7 @@ gclue_web_source_real_refresh_async (GClueWebSource *source, + task = g_task_new (source, cancellable, callback, user_data); + g_task_set_source_tag (task, gclue_web_source_real_refresh_async); + +- refresh_accuracy_level (source); ++ gclue_web_source_refresh_available_accuracy_level (source); + + if (!gclue_location_source_get_active (GCLUE_LOCATION_SOURCE (source))) { + g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED, +@@ -215,8 +212,8 @@ query_callback (GObject *source_object, + } + } + +-static void +-refresh_accuracy_level (GClueWebSource *web) ++void ++gclue_web_source_refresh_available_accuracy_level (GClueWebSource *web) + { + GClueAccuracyLevel new, existing; + +@@ -282,7 +279,7 @@ locate_url_checked_cb (GObject *source_object, + if (!current_location || (g_get_real_time () / G_USEC_PER_SEC) + > (gclue_location_get_timestamp (current_location) + WEB_LOCATION_TIMEOUT)) { + g_debug ("Network changed: Refreshing"); +- refresh_accuracy_level (web); ++ gclue_web_source_refresh_available_accuracy_level (web); + if (gclue_location_source_get_active (GCLUE_LOCATION_SOURCE (web))) + gclue_web_source_refresh (web); + else +diff --git a/src/gclue-web-source.h b/src/gclue-web-source.h +index e466beb..7603bfa 100644 +--- a/src/gclue-web-source.h ++++ b/src/gclue-web-source.h +@@ -90,6 +90,7 @@ struct _GClueWebSourceClass { + }; + + void gclue_web_source_refresh (GClueWebSource *source); ++void gclue_web_source_refresh_available_accuracy_level (GClueWebSource *source); + void gclue_web_source_set_submit_source (GClueWebSource *source, + GClueLocationSource *submit_source); + void gclue_web_source_set_locate_url (GClueWebSource *source, +-- +2.48.1 + + +From a7286f6759770f1c50aa97a6d503a094a7895bc5 Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Sun, 19 Jan 2025 20:33:39 +0200 +Subject: [PATCH] wifi: Accuracy level is now NONE when there is no interface + +IP-only queries are handled by the IP source. +--- + src/gclue-wifi.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/src/gclue-wifi.c b/src/gclue-wifi.c +index 62ae1b1..728c438 100644 +--- a/src/gclue-wifi.c ++++ b/src/gclue-wifi.c +@@ -892,10 +892,8 @@ gclue_wifi_get_available_accuracy_level (GClueWebSource *source, + GClueWifi *wifi = GCLUE_WIFI (source); + GClueWifiPrivate *priv = wifi->priv; + +- if (!net_available) ++ if (!net_available || !priv->interface) + return GCLUE_ACCURACY_LEVEL_NONE; +- else if (!priv->interface) +- return GCLUE_ACCURACY_LEVEL_CITY; + else + return MIN (get_accuracy_level (wifi), GCLUE_ACCURACY_LEVEL_STREET); + } +-- +2.48.1 + + +From ba374e669610fae1f89ccfc99b52c52e1d3fa5ab Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Sat, 18 Jan 2025 19:32:37 +0200 +Subject: [PATCH] wifi: Do not create a location without a BSS list + +Create a new location only when a scan has finished and it contains a +non-empty set of BSS's: + +Replace full source refresh with available accuracy level refresh when +there is no wifi interface on initialization, when the wifi source is +not set to active, and on wifi interface removal. + +Don't refresh the source or available accuracy level on construction, +when there is no configured interface yet. + +Return G_IO_ERROR_NOT_INITIALIZED on refresh_async() if the BSS list +from a scan is empty. +--- + src/gclue-wifi.c | 37 +++++++++++++++++++++++-------------- + 1 file changed, 23 insertions(+), 14 deletions(-) + +diff --git a/src/gclue-wifi.c b/src/gclue-wifi.c +index 728c438..24bba53 100644 +--- a/src/gclue-wifi.c ++++ b/src/gclue-wifi.c +@@ -647,8 +647,7 @@ connect_bss_signals (GClueWifi *wifi) + if (priv->bss_added_id != 0) + return; + if (priv->interface == NULL) { +- gclue_web_source_refresh (GCLUE_WEB_SOURCE (wifi)); +- ++ gclue_web_source_refresh_available_accuracy_level (GCLUE_WEB_SOURCE (wifi)); + return; + } + +@@ -934,7 +933,8 @@ on_interface_proxy_ready (GObject *source_object, + if (gclue_location_source_get_active (GCLUE_LOCATION_SOURCE (wifi))) + connect_bss_signals (wifi); + else +- gclue_web_source_refresh (GCLUE_WEB_SOURCE (wifi)); ++ gclue_web_source_refresh_available_accuracy_level (GCLUE_WEB_SOURCE (wifi)); ++ + } + + static void +@@ -984,7 +984,7 @@ on_interface_removed (WPASupplicant *supplicant, + g_debug ("Removed interface was the WiFi source"); + } + +- gclue_web_source_refresh (GCLUE_WEB_SOURCE (wifi)); ++ gclue_web_source_refresh_available_accuracy_level (GCLUE_WEB_SOURCE (wifi)); + } + + static void +@@ -1037,7 +1037,7 @@ gclue_wifi_constructed (GObject *object) + if (error) + g_warning ("Failed to connect to wpa_supplicant service: %s", + error->message); +- goto refresh_n_exit; ++ return; + } + + g_signal_connect_object (priv->supplicant, +@@ -1055,9 +1055,6 @@ gclue_wifi_constructed (GObject *object) + interfaces[0], + NULL, + wifi); +- +-refresh_n_exit: +- gclue_web_source_refresh (GCLUE_WEB_SOURCE (object)); + } + + static void +@@ -1419,16 +1416,28 @@ gclue_wifi_refresh_async (GClueWebSource *source, + gpointer user_data) + { + GClueWifi *wifi = GCLUE_WIFI (source); +- g_autoptr(GTask) task = g_task_new (source, cancellable, callback, user_data); +- g_autoptr(GPtrArray) bss_array = get_location_cache_bss_array (wifi); +- g_autoptr(GVariant) cache_key = get_location_cache_hashtable_key (wifi, bss_array); +- g_autoptr(GArray) signal_array = get_location_cache_signal_array (wifi, bss_array); +- GClueLocation *cached_location = find_cached_location (wifi->priv->location_cache, +- cache_key, signal_array); ++ GClueLocation *cached_location; + RefreshTaskData *tdata; ++ g_autoptr(GTask) task = g_task_new (source, cancellable, callback, user_data); ++ g_autoptr(GPtrArray) bss_array = NULL; ++ g_autoptr(GVariant) cache_key = NULL; ++ g_autoptr(GArray) signal_array = NULL; + + g_task_set_source_tag (task, gclue_wifi_refresh_async); + ++ /* Don't create a location without a BSS list, we have the IP source for that */ ++ if (!wifi->priv->bss_proxies || g_hash_table_size (wifi->priv->bss_proxies) < 1) { ++ GError *error = g_error_new (G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED, ++ "Empty BSS list"); ++ g_task_return_error (task, error); ++ return; ++ } ++ ++ bss_array = get_location_cache_bss_array (wifi); ++ cache_key = get_location_cache_hashtable_key (wifi, bss_array); ++ signal_array = get_location_cache_signal_array (wifi, bss_array); ++ cached_location = find_cached_location (wifi->priv->location_cache, cache_key, signal_array); ++ + if (gclue_location_source_get_active (GCLUE_LOCATION_SOURCE (source))) { + /* Try the cache. */ + if (cached_location != NULL) { +-- +2.48.1 + + +From 3554287eb6c5e9d24c593060010e780d918c1fdc Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Thu, 5 Dec 2024 16:41:05 +0200 +Subject: [PATCH] ip: Add 'reallyfreegeoip' method + +This method uses the JSON API of reallyfreegeoip.org to determine a +city-level location. +--- + data/geoclue.5.in | 1 + + src/gclue-config.c | 3 ++- + src/gclue-ip.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 65 insertions(+), 1 deletion(-) + +diff --git a/data/geoclue.5.in b/data/geoclue.5.in +index ca58f0d..6b654fe 100644 +--- a/data/geoclue.5.in ++++ b/data/geoclue.5.in +@@ -51,6 +51,7 @@ Method (backend) to use for IP location. Currently implemented are: + "ichnaea": Use the Ichnaea API with the URL from the wifi source. + .br + "gmaps": Use the location determined by Google Maps. ++"reallyfreegeoip": Use the location from reallyfreegeoip.org. + .br + .IP \fB[network-nmea] + .br +diff --git a/src/gclue-config.c b/src/gclue-config.c +index 71de78b..5605520 100644 +--- a/src/gclue-config.c ++++ b/src/gclue-config.c +@@ -645,7 +645,8 @@ out: + } + if (priv->enable_ip_source && (!string_present (priv->ip_method) || + (g_strcmp0 (priv->ip_method, "ichnaea") != 0 && +- g_strcmp0 (priv->ip_method, "gmaps") != 0))) { ++ g_strcmp0 (priv->ip_method, "gmaps") != 0 && ++ g_strcmp0 (priv->ip_method, "reallyfreegeoip") != 0))) { + g_warning ("Unknown IP source method '%s', disabling source", priv->ip_method); + priv->enable_ip_source = FALSE; + g_clear_pointer (&priv->ip_method, g_free); +diff --git a/src/gclue-ip.c b/src/gclue-ip.c +index 4d018c4..8449f06 100644 +--- a/src/gclue-ip.c ++++ b/src/gclue-ip.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include "config.h" + #include "gclue-ip.h" +@@ -144,6 +145,62 @@ gmaps_parse_response (GClueWebSource *source, + return location; + } + ++/* reallyfreegeoip method */ ++ ++#define REALLYFREEGEOIP_URL "https://reallyfreegeoip.org/json/" ++#define REALLYFREEGEOIP_ACCURACY (20000.0) ++ ++static SoupMessage * ++reallyfreegeoip_create_query (GClueWebSource *source, ++ const char **query_data_description, ++ GError **error) ++{ ++ g_autoptr(SoupMessage) query = NULL; ++ ++ query = soup_message_new ("GET", REALLYFREEGEOIP_URL); ++ if (query_data_description) { ++ *query_data_description = "reallyfreegeoip IP"; ++ } ++ ++ return g_steal_pointer (&query); ++} ++ ++static GClueLocation * ++reallyfreegeoip_parse_response (GClueWebSource *source, ++ const char *response, ++ GError **error) ++{ ++ g_autoptr(JsonParser) parser = NULL; ++ JsonNode *node; ++ JsonObject *object; ++ double latitude, longitude, accuracy; ++ GClueLocation *location; ++ ++ parser = json_parser_new (); ++ ++ if (!json_parser_load_from_data (parser, response, -1, error)) ++ return NULL; ++ ++ node = json_parser_get_root (parser); ++ object = json_node_get_object (node); ++ ++ latitude = json_object_get_double_member (object, "latitude"); ++ longitude = json_object_get_double_member (object, "longitude"); ++ accuracy = REALLYFREEGEOIP_ACCURACY; ++ g_debug ("Parsed reallyfreegeoip values lat=%.8f, lon=%.8f, default accuracy=%.0f", ++ latitude, longitude, accuracy); ++ if (latitude <= -180.0 || latitude > 180.0 || ++ longitude > 90.0 || longitude < -90.0) { ++ g_warning ("reallyfreegeoip coordinates are invalid: lat=%.8f, lon=%.8f", ++ latitude, longitude); ++ return NULL; ++ } ++ location = gclue_location_new (latitude, longitude, accuracy, ++ gclue_web_source_get_query_data_description(source)); ++ ++ return location; ++} ++ + /* GClueIp common */ + + static void +@@ -209,6 +266,9 @@ gclue_ip_class_init (GClueIpClass *klass) + } else if (g_strcmp0 (method, "gmaps") == 0) { + web_class->create_query = gmaps_create_query; + web_class->parse_response = gmaps_parse_response; ++ } else if (g_strcmp0 (method, "reallyfreegeoip") == 0) { ++ web_class->create_query = reallyfreegeoip_create_query; ++ web_class->parse_response = reallyfreegeoip_parse_response; + } else { + g_error ("Unknown IP method '%s'", method); + } +@@ -237,6 +297,8 @@ gclue_ip_init (GClueIp *ip) + ("center=[0-9\\.]*%2C[0-9\\.]*&zoom=[0-9]*&", + G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, NULL); + gclue_web_source_set_locate_url (web_source, GMAPS_URL); ++ } else if (g_strcmp0 (method, "reallyfreegeoip") == 0) { ++ gclue_web_source_set_locate_url (web_source, REALLYFREEGEOIP_URL); + } else { + g_error ("Unknown IP method '%s'", method); + } +-- +2.48.1 + + +From 77e62780bbce294d72e031e3c5307da9c6cdef5d Mon Sep 17 00:00:00 2001 +From: Teemu Ikonen +Date: Thu, 30 Jan 2025 19:10:02 +0200 +Subject: [PATCH] data: Fix the default IP source method in man page + +--- + data/geoclue.5.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/data/geoclue.5.in b/data/geoclue.5.in +index 6b654fe..091e6c8 100644 +--- a/data/geoclue.5.in ++++ b/data/geoclue.5.in +@@ -44,7 +44,7 @@ IP source configuration options + Enable the GeoIP source + .br + .IP +-.B \fBmethod=gmaps ++.B \fBmethod=ichnaea + .br + Method (backend) to use for IP location. Currently implemented are: + .br +-- +2.48.1 + diff --git a/geoclue2.spec b/geoclue2.spec index 0ff2b0d..4d0d5ab 100644 --- a/geoclue2.spec +++ b/geoclue2.spec @@ -1,6 +1,6 @@ Name: geoclue2 -Version: 2.7.0 -Release: 8%{?dist} +Version: 2.7.2 +Release: 1%{?dist} Summary: Geolocation service License: GPL-2.0-or-later @@ -8,10 +8,13 @@ URL: http://www.freedesktop.org/wiki/Software/GeoClue/ Source0: https://gitlab.freedesktop.org/geoclue/geoclue/-/archive/%{version}/geoclue-%{version}.tar.bz2 Source1: geoclue2.sysusers -Patch: 0001-remove-mozilla-location-service.patch +# Backport from upstream +## Generated with: git format-patch -N --stdout 2.7.2...master > geoclue-2.7.2-git41-backports.patch +Patch0: geoclue-2.7.2-git41-backports.patch BuildRequires: avahi-glib-devel BuildRequires: gettext +BuildRequires: git-core BuildRequires: glib2-devel BuildRequires: gobject-introspection-devel BuildRequires: gtk-doc @@ -71,11 +74,18 @@ The %{name}-demos package contains demo applications that use %{name}. %prep -%autosetup -p1 -n geoclue-%{version} +%autosetup -n geoclue-%{version} -S git_am + + +%conf +%meson \ + -Ddbus-srv-user=geoclue \ + -Ddefault-wifi-url="https://api.beacondb.net/v1/geolocate" \ + -Ddefault-wifi-submit-url="https://api.beacondb.net/v2/geosubmit" \ + %{nil} %build -%meson -Ddbus-srv-user=geoclue %meson_build @@ -107,12 +117,12 @@ exit 0 %config %{_sysconfdir}/geoclue/ %dir %{_libexecdir}/geoclue-2.0 %dir %{_libexecdir}/geoclue-2.0/demos -%{_sysconfdir}/dbus-1/system.d/org.freedesktop.GeoClue2.conf -%{_sysconfdir}/dbus-1/system.d/org.freedesktop.GeoClue2.Agent.conf %{_sysconfdir}/xdg/autostart/geoclue-demo-agent.desktop %{_libexecdir}/geoclue -%{_datadir}/polkit-1/rules.d/org.freedesktop.GeoClue2.rules +%{_datadir}/dbus-1/system.d/org.freedesktop.GeoClue2.conf +%{_datadir}/dbus-1/system.d/org.freedesktop.GeoClue2.Agent.conf %{_datadir}/dbus-1/system-services/org.freedesktop.GeoClue2.service +%{_datadir}/polkit-1/rules.d/org.freedesktop.GeoClue2.rules %{_datadir}/applications/geoclue-demo-agent.desktop %{_mandir}/man5/geoclue.5* %{_unitdir}/geoclue.service @@ -148,6 +158,12 @@ exit 0 %changelog +* Wed Feb 12 2025 Neal Gompa - 2.7.2-1 +- Update to 2.7.2 + + Backport fixes from upstream to use BeaconDB + + Use BeaconDB for the default location services source + Resolves: RHEL-79063 + * Mon Feb 03 2025 Milan Crha - 2.7.0-8 - Resolves: RHEL-44940 (Remove Mozilla Location Service) diff --git a/sources b/sources index d10249c..14118ee 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (geoclue-2.7.0.tar.bz2) = 2314242f529b9011ee5da6e8cfc657568853769e4d38b8e7c604097a747dd5705d9f84dcd2763cdacb9f014e15b63fbb8356d6cb488ba91334cda87c11e4ee7d +SHA512 (geoclue-2.7.2.tar.bz2) = 2300fca3c088f1bef29ecf1b5c82f6e91fcf886f3aa9ce1e53054e0c430fb3fc810ae8f580469a7975942c5a4852c75bac123a58c7c389d0ef116dc324d6463c