[geocode-glib] lib: Return a location from geocode_ipclient_search()
- From: Bastien Nocera <hadess src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geocode-glib] lib: Return a location from geocode_ipclient_search()
- Date: Tue, 2 Apr 2013 17:44:21 +0000 (UTC)
commit d589297a653588beb5112a614d3e6aaad05cbfd3
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date: Fri Mar 22 02:28:18 2013 +0200
lib: Return a location from geocode_ipclient_search()
This API is a lot more useful if we provide a parsed GeocodeLocation
object to the caller rather than just the raw JSON string we get as
response from server.
https://bugzilla.gnome.org/show_bug.cgi?id=696526
geocode-glib/geocode-glib-private.h | 3 +
geocode-glib/geocode-glib.symbols | 1 +
geocode-glib/geocode-ipclient.c | 116 ++++++++++++++++++++++++++++++++---
geocode-glib/geocode-ipclient.h | 11 ++--
geocode-glib/test-geoip.c | 64 ++++++++++++--------
5 files changed, 155 insertions(+), 40 deletions(-)
---
diff --git a/geocode-glib/geocode-glib-private.h b/geocode-glib/geocode-glib-private.h
index d6b8610..2393c9e 100644
--- a/geocode-glib/geocode-glib-private.h
+++ b/geocode-glib/geocode-glib-private.h
@@ -24,6 +24,7 @@
#define GEOCODE_GLIB_PRIVATE_H
#include <glib.h>
+#include "geocode-location.h"
G_BEGIN_DECLS
@@ -41,6 +42,8 @@ GList *_geocode_parse_search_json (const char *contents,
GError **error);
GFile *_get_resolve_query_for_params (GHashTable *orig_ht,
gboolean reverse);
+GeocodeLocation *_geocode_ip_json_to_location (const char *json,
+ GError **error);
char *_geocode_object_get_lang (void);
diff --git a/geocode-glib/geocode-glib.symbols b/geocode-glib/geocode-glib.symbols
index 5245bf9..e8d8e2d 100644
--- a/geocode-glib/geocode-glib.symbols
+++ b/geocode-glib/geocode-glib.symbols
@@ -19,6 +19,7 @@ geocode_reverse_resolve
geocode_error_quark
_geocode_parse_search_json
_geocode_parse_resolve_json
+_geocode_ip_json_to_location
geocode_ipclient_get_type
geocode_ipclient_new
geocode_ipclient_new_for_ip
diff --git a/geocode-glib/geocode-ipclient.c b/geocode-glib/geocode-ipclient.c
index 47e5194..34c34c8 100644
--- a/geocode-glib/geocode-ipclient.c
+++ b/geocode-glib/geocode-ipclient.c
@@ -23,7 +23,11 @@
#include <stdlib.h>
#include <glib.h>
#include <libsoup/soup.h>
+#include <json-glib/json-glib.h>
+#include "geocode-glib-private.h"
#include "geocode-ipclient.h"
+#include "geocode-error.h"
+#include "geocode-ip-server/geoip-server.h"
/**
* SECTION:geocode-ipclient
@@ -280,6 +284,92 @@ geocode_ipclient_search_async (GeocodeIpclient *ipclient,
g_object_unref (query);
}
+static gboolean
+parse_server_error (JsonObject *object, GError **error)
+{
+ GeoipServerError server_error_code;
+ int error_code;
+ const char *error_message;
+
+ if (!json_object_has_member (object, "error_code"))
+ return FALSE;
+
+ server_error_code = json_object_get_int_member (object, "error_code");
+ switch (server_error_code) {
+ case INVALID_IP_ADDRESS_ERR:
+ error_code = GEOCODE_ERROR_INVALID_ARGUMENTS;
+ break;
+ case INVALID_ENTRY_ERR:
+ error_code = GEOCODE_ERROR_NO_MATCHES;
+ break;
+ case DATABASE_ERR:
+ error_code = GEOCODE_ERROR_INTERNAL_SERVER;
+ break;
+ }
+
+ error_message = json_object_get_string_member (object, "error_message");
+
+ g_set_error_literal (error,
+ GEOCODE_ERROR,
+ error_code,
+ error_message);
+
+ return TRUE;
+}
+
+GeocodeLocation *
+_geocode_ip_json_to_location (const char *json,
+ GError **error)
+{
+ JsonParser *parser;
+ JsonNode *node;
+ JsonObject *object;
+ GeocodeLocation *location;
+ char *desc = NULL;
+
+ parser = json_parser_new ();
+
+ if (!json_parser_load_from_data (parser, json, -1, error))
+ return NULL;
+
+ node = json_parser_get_root (parser);
+ object = json_node_get_object (node);
+
+ if (parse_server_error (object, error))
+ return NULL;
+
+ location = geocode_location_new (0, 0);
+ location->latitude = json_object_get_double_member (object, "latitude");
+ location->longitude = json_object_get_double_member (object, "longitude");
+
+ if (json_object_has_member (object, "country_name")) {
+ if (json_object_has_member (object, "region_name")) {
+ if (json_object_has_member (object, "city")) {
+ desc = g_strdup_printf ("%s, %s, %s",
+ json_object_get_string_member (object, "city"),
+ json_object_get_string_member (object,
"region_name"),
+ json_object_get_string_member (object,
"country_name"));
+ } else {
+ desc = g_strdup_printf ("%s, %s",
+ json_object_get_string_member (object,
"region_name"),
+ json_object_get_string_member (object,
"country_name"));
+ }
+ } else {
+ desc = g_strdup_printf ("%s",
+ json_object_get_string_member (object, "country_name"));
+ }
+ }
+
+ if (desc != NULL) {
+ geocode_location_set_description (location, desc);
+ g_free (desc);
+ }
+
+ g_object_unref (parser);
+
+ return location;
+}
+
/**
* geocode_ipclient_search_finish:
* @ipclient: a #GeocodeIpclient representing a query
@@ -288,17 +378,17 @@ geocode_ipclient_search_async (GeocodeIpclient *ipclient,
*
* Finishes a geolocation search operation. See geocode_ipclient_search_async().
*
- * Returns: a string containing the result of the query in JSON format
- * or %NULL in case of errors.
- * Free the returned string with g_free() when done.
+ * Returns: (transfer full): A #GeocodeLocation object or %NULL in case of
+ * errors. Free the returned object with g_object_unref() when done.
**/
-char *
+GeocodeLocation *
geocode_ipclient_search_finish (GeocodeIpclient *ipclient,
GAsyncResult *res,
GError **error)
{
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
char *contents = NULL;
+ GeocodeLocation *location;
g_return_val_if_fail (GEOCODE_IS_IPCLIENT (ipclient), NULL);
@@ -308,7 +398,10 @@ geocode_ipclient_search_finish (GeocodeIpclient *ipclient,
return NULL;
contents = g_simple_async_result_get_op_res_gpointer (simple);
- return contents;
+ location = _geocode_ip_json_to_location (contents, error);
+ g_free (contents);
+
+ return location;
}
/**
@@ -318,16 +411,16 @@ geocode_ipclient_search_finish (GeocodeIpclient *ipclient,
*
* Gets the geolocation data for an IP address from the server.
*
- * Returns: a string containing the result of the query in JSON format
- * or %NULL in case of errors.
- * Free the returned string with g_free() when done.
+ * Returns: (transfer full): A #GeocodeLocation object or %NULL in case of
+ * errors. Free the returned object with g_object_unref() when done.
**/
-char *
+GeocodeLocation *
geocode_ipclient_search (GeocodeIpclient *ipclient,
GError **error)
{
char *contents;
GFile *query;
+ GeocodeLocation *location;
g_return_val_if_fail (GEOCODE_IS_IPCLIENT (ipclient), NULL);
g_return_val_if_fail (ipclient->priv->server != NULL, NULL);
@@ -347,5 +440,8 @@ geocode_ipclient_search (GeocodeIpclient *ipclient,
}
g_object_unref (query);
- return contents;
+ location = _geocode_ip_json_to_location (contents, error);
+ g_free (contents);
+
+ return location;
}
diff --git a/geocode-glib/geocode-ipclient.h b/geocode-glib/geocode-ipclient.h
index ab9e7d9..7bd26da 100644
--- a/geocode-glib/geocode-ipclient.h
+++ b/geocode-glib/geocode-ipclient.h
@@ -25,6 +25,7 @@
#include <glib.h>
#include <gio/gio.h>
+#include "geocode-location.h"
G_BEGIN_DECLS
@@ -71,12 +72,12 @@ void geocode_ipclient_search_async (GeocodeIpclient *ipclient,
GAsyncReadyCallback callback,
gpointer user_data);
-char *geocode_ipclient_search_finish (GeocodeIpclient *ipclient,
- GAsyncResult *res,
- GError **error);
+GeocodeLocation *geocode_ipclient_search_finish (GeocodeIpclient *ipclient,
+ GAsyncResult *res,
+ GError **error);
-char *geocode_ipclient_search (GeocodeIpclient *ipclient,
- GError **error);
+GeocodeLocation *geocode_ipclient_search (GeocodeIpclient *ipclient,
+ GError **error);
G_END_DECLS
diff --git a/geocode-glib/test-geoip.c b/geocode-glib/test-geoip.c
index 4b1881f..895e643 100644
--- a/geocode-glib/test-geoip.c
+++ b/geocode-glib/test-geoip.c
@@ -9,30 +9,39 @@
static GMainLoop *loop = NULL;
+typedef struct {
+ const char *ip;
+
+ double expected_latitude;
+ double expected_longitude;
+ const char *expected_description;
+} TestData;
+
static void
test_search (gconstpointer data)
{
GeocodeIpclient *ipclient;
GError *error = NULL;
- char *contents;
- const char *ip;
+ GeocodeLocation *location;
+ TestData *test_data = (TestData *) data;
- ip = (const char *) data;
- if (ip)
- ipclient = geocode_ipclient_new_for_ip (ip);
- else
+ if (test_data->ip)
+ ipclient = geocode_ipclient_new_for_ip (test_data->ip);
+ else {
ipclient = geocode_ipclient_new ();
-
- contents = geocode_ipclient_search (ipclient, &error);
- if (!contents) {
+ }
+ location = geocode_ipclient_search (ipclient, &error);
+ if (!location) {
g_warning ("Failed at getting the geolocation information: %s", error->message);
g_error_free (error);
}
- g_assert (contents != NULL);
- g_assert (strstr (contents, "\"ERROR\"") == NULL);
+ g_assert (location != NULL);
+ g_assert (location->latitude == test_data->expected_latitude);
+ g_assert (location->longitude == test_data->expected_longitude);
+ g_assert (location->description != NULL &&
+ strcmp(location->description, test_data->expected_description) == 0);
+ geocode_location_free (location);
g_object_unref (ipclient);
- g_print ("%s\n", contents);
- g_free (contents);
}
static void
@@ -42,31 +51,30 @@ print_geolocation_info_cb (GObject *source_object,
{
GeocodeIpclient *object = (GeocodeIpclient *) source_object;
GError *error = NULL;
- char *results;
+ GeocodeLocation *location;
- results = geocode_ipclient_search_finish (object, res, &error);
- if (results == NULL) {
+ location = geocode_ipclient_search_finish (object, res, &error);
+ if (location == NULL) {
g_message ("Failed to search the geolocation info: %s", error->message);
g_error_free (error);
exit (1);
}
- g_print ("%s\n", results);
- g_free (results);
+ g_print ("Location: %s (%f,%f)\n", location->description, location->latitude, location->longitude);
+ geocode_location_free (location);
g_object_unref (object);
exit (0);
}
-
int main (int argc, char **argv)
{
GError *error = NULL;
GOptionContext *context;
GeocodeIpclient *ipclient;
- char *ip = NULL;
+ TestData data = { NULL, 0.0f, 0.0f, NULL };
gboolean regr = FALSE;
const GOptionEntry entries[] = {
- { "ip", 0, 0, G_OPTION_ARG_STRING, &ip, "The ip address for which to search the geolocation
data", NULL },
+ { "ip", 0, 0, G_OPTION_ARG_STRING, &data.ip, "The ip address for which to search the
geolocation data", NULL },
{ "regr", 0, 0, G_OPTION_ARG_NONE, ®r, "Run the default testcases", NULL },
{ NULL }
};
@@ -86,13 +94,19 @@ int main (int argc, char **argv)
}
if (regr == TRUE) {
- g_test_add_data_func ("/geoip/search_with_ip", "24.24.24.24", test_search);
- g_test_add_data_func ("/geocode/search", NULL, test_search);
+ data.expected_latitude = 43.089199f;
+ data.expected_longitude = -76.025002f;
+ data.expected_description = "East Syracuse, New York, United States";
+
+ g_test_add_data_func ("/geocode/search", &data, test_search);
+
+ data.ip = "24.24.24.24";
+ g_test_add_data_func ("/geoip/search_with_ip", &data, test_search);
return g_test_run ();
}
- if (ip)
- ipclient = geocode_ipclient_new_for_ip (ip);
+ if (data.ip)
+ ipclient = geocode_ipclient_new_for_ip (data.ip);
else
ipclient = geocode_ipclient_new ();
geocode_ipclient_search_async (ipclient, NULL, print_geolocation_info_cb, NULL);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]