diff options
Diffstat (limited to '.pc/tizen.patch/providers/skyhook')
-rwxr-xr-x | .pc/tizen.patch/providers/skyhook/Makefile.am | 35 | ||||
-rwxr-xr-x | .pc/tizen.patch/providers/skyhook/geoclue-skyhook.c | 303 | ||||
-rwxr-xr-x | .pc/tizen.patch/providers/skyhook/geoclue-skyhook.provider | 8 |
3 files changed, 346 insertions, 0 deletions
diff --git a/.pc/tizen.patch/providers/skyhook/Makefile.am b/.pc/tizen.patch/providers/skyhook/Makefile.am new file mode 100755 index 0000000..a6e2107 --- /dev/null +++ b/.pc/tizen.patch/providers/skyhook/Makefile.am @@ -0,0 +1,35 @@ +libexec_PROGRAMS = \ + geoclue-skyhook + +geoclue_skyhook_SOURCES = \ + geoclue-skyhook.c + +geoclue_skyhook_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -I$(top_srcdir)/src \ + $(GEOCLUE_CFLAGS) \ + $(SKYHOOK_CFLAGS) + +geoclue_skyhook_LDADD = \ + $(GEOCLUE_LIBS) \ + $(SKYHOOK_LIBS) \ + $(top_builddir)/src/libconnectivity.la \ + $(top_builddir)/geoclue/libgeoclue.la + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-skyhook.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Skyhook.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) + +DISTCLEANFILES = \ + $(service_DATA) diff --git a/.pc/tizen.patch/providers/skyhook/geoclue-skyhook.c b/.pc/tizen.patch/providers/skyhook/geoclue-skyhook.c new file mode 100755 index 0000000..5af7b45 --- /dev/null +++ b/.pc/tizen.patch/providers/skyhook/geoclue-skyhook.c @@ -0,0 +1,303 @@ +/* + * Geoclue + * geoclue-skyhook.c - A skyhook.com-based Address/Position provider + * + * Author: Bastien Nocera <hadess@hadess.net> + * Copyright 2009 Bastien Nocera + */ + +#include <config.h> + +#include <time.h> +#include <string.h> +#include <errno.h> + +#include <glib-object.h> +#include <dbus/dbus-glib-bindings.h> +#include <libsoup/soup.h> +#include <libxml/xpathInternals.h> + +#include <geoclue/gc-web-service.h> +#include <geoclue/gc-provider.h> +#include <geoclue/geoclue-error.h> +#include <geoclue/gc-iface-position.h> + +#include "connectivity.h" + +#define GEOCLUE_DBUS_SERVICE_SKYHOOK "org.freedesktop.Geoclue.Providers.Skyhook" +#define GEOCLUE_DBUS_PATH_SKYHOOK "/org/freedesktop/Geoclue/Providers/Skyhook" +#define SKYHOOK_URL "https://api.skyhookwireless.com/wps2/location" +#define SKYHOOK_LAT_XPATH "//prefix:latitude" +#define SKYHOOK_LON_XPATH "//prefix:longitude" +#define USER_AGENT "Geoclue "VERSION + +#define GEOCLUE_TYPE_SKYHOOK (geoclue_skyhook_get_type ()) +#define GEOCLUE_SKYHOOK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_SKYHOOK, GeoclueSkyhook)) + +#define QUERY_START "<?xml version=\'1.0\'?><LocationRQ xmlns=\'http://skyhookwireless.com/wps/2005\' version=\'2.6\' street-address-lookup=\'full\'><authentication version=\'2.0\'><simple><username>beta</username><realm>js.loki.com</realm></simple></authentication>" +#define QUERY_AP "<access-point><mac>%s</mac><signal-strength>%d</signal-strength></access-point>" +#define QUERY_END "</LocationRQ>" + +typedef struct _GeoclueSkyhook { + GcProvider parent; + GMainLoop *loop; + SoupSession *session; + GeoclueConnectivity *conn; +} GeoclueSkyhook; + +typedef struct _GeoclueSkyhookClass { + GcProviderClass parent_class; +} GeoclueSkyhookClass; + + +static void geoclue_skyhook_init (GeoclueSkyhook *skyhook); +static void geoclue_skyhook_position_init (GcIfacePositionClass *iface); + +G_DEFINE_TYPE_WITH_CODE (GeoclueSkyhook, geoclue_skyhook, GC_TYPE_PROVIDER, + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POSITION, + geoclue_skyhook_position_init)) + + +/* Geoclue interface implementation */ +static gboolean +geoclue_skyhook_get_status (GcIfaceGeoclue *iface, + GeoclueStatus *status, + GError **error) +{ + /* Assume available so long as all the requirements are satisfied + ie: Network is available */ + *status = GEOCLUE_STATUS_AVAILABLE; + return TRUE; +} + +static void +_shutdown (GcProvider *provider) +{ + GeoclueSkyhook *skyhook = GEOCLUE_SKYHOOK (provider); + g_main_loop_quit (skyhook->loop); +} + +static void +add_ap (gpointer key, + gpointer value, + gpointer data) +{ + char *mac; + char **split; + + /* Remove the ":" */ + split = g_strsplit (key, ":", -1); + mac = g_strjoinv ("", split); + g_strfreev (split); + + g_string_append_printf (data, QUERY_AP, mac, GPOINTER_TO_INT (value)); + g_free (mac); +} + +static char * +create_post_query (GeoclueConnectivity *conn) +{ + GHashTable *ht; + GString *str; + + ht = geoclue_connectivity_get_aps (conn); + if (ht == NULL) + return NULL; + str = g_string_new (QUERY_START); + g_hash_table_foreach (ht, add_ap, str); + g_string_append (str, QUERY_END); + g_hash_table_destroy (ht); + + return g_string_free (str, FALSE); +} + +static gboolean +get_double (xmlXPathContext *xpath_ctx, char *xpath, gdouble *value) +{ + xmlXPathObject *obj = NULL; + + obj = xmlXPathEvalExpression (BAD_CAST (xpath), xpath_ctx); + if (obj && + (!obj->nodesetval || xmlXPathNodeSetIsEmpty (obj->nodesetval))) { + xmlXPathFreeObject (obj); + return FALSE; + } + *value = xmlXPathCastNodeSetToNumber (obj->nodesetval); + xmlXPathFreeObject (obj); + return TRUE; +} + +static gboolean +parse_response (const char *body, gdouble *latitude, gdouble *longitude) +{ + xmlDocPtr doc; + xmlXPathContext *xpath_ctx; + gboolean ret = TRUE; + + doc = xmlParseDoc (BAD_CAST (body)); + if (!doc) + return FALSE; + + xpath_ctx = xmlXPathNewContext(doc); + if (!xpath_ctx) { + xmlFreeDoc (doc); + return FALSE; + } + xmlXPathRegisterNs (xpath_ctx, BAD_CAST ("prefix"), BAD_CAST("http://skyhookwireless.com/wps/2005")); + if (get_double (xpath_ctx, SKYHOOK_LAT_XPATH, latitude) == FALSE) { + ret = FALSE; + } else if (get_double (xpath_ctx, SKYHOOK_LON_XPATH, longitude) == FALSE) { + ret = FALSE; + } + xmlXPathFreeContext (xpath_ctx); + xmlFreeDoc (doc); + + return ret; +} + +/* Position interface implementation */ + +static gboolean +geoclue_skyhook_get_position (GcIfacePosition *iface, + GeocluePositionFields *fields, + int *timestamp, + double *latitude, + double *longitude, + double *altitude, + GeoclueAccuracy **accuracy, + GError **error) +{ + GeoclueSkyhook *skyhook; + char *query; + SoupMessage *msg; + + skyhook = (GEOCLUE_SKYHOOK (iface)); + + *fields = GEOCLUE_POSITION_FIELDS_NONE; + if (timestamp) + *timestamp = time (NULL); + + query = create_post_query (skyhook->conn); + if (query == NULL) { + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Router mac address query failed"); + /* TODO: set status == error ? */ + return FALSE; + } + + msg = soup_message_new ("POST", SKYHOOK_URL); + soup_message_headers_append (msg->request_headers, "User-Agent", USER_AGENT); + soup_message_set_request (msg, + "text/xml", + SOUP_MEMORY_TAKE, + query, + strlen (query)); + soup_session_send_message (skyhook->session, msg); + if (msg->response_body == NULL || msg->response_body->data == NULL) { + g_object_unref (msg); + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Failed to query web service"); + return FALSE; + } + + if (strstr (msg->response_body->data, "<error>") != NULL) { + g_object_unref (msg); + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Web service returned an error"); + return FALSE; + } + + if (parse_response (msg->response_body->data, latitude, longitude) == FALSE) { + g_object_unref (msg); + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Couldn't parse response from web service"); + return FALSE; + } + + if (latitude) + *fields |= GEOCLUE_POSITION_FIELDS_LATITUDE; + if (longitude) + *fields |= GEOCLUE_POSITION_FIELDS_LONGITUDE; + + if (accuracy) { + if (*fields == GEOCLUE_POSITION_FIELDS_NONE) { + *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, + 0, 0); + } else { + /* Educated guess. Skyhook are typically hand pointed on + * a map, or geocoded from address, so should be fairly + * accurate */ + *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_STREET, + 0, 0); + } + } + + return TRUE; +} + +static void +geoclue_skyhook_finalize (GObject *obj) +{ + GeoclueSkyhook *skyhook = GEOCLUE_SKYHOOK (obj); + + if (skyhook->conn != NULL) { + g_object_unref (skyhook->conn); + skyhook->conn = NULL; + } + g_object_unref (skyhook->session); + + ((GObjectClass *) geoclue_skyhook_parent_class)->finalize (obj); +} + + +/* Initialization */ + +static void +geoclue_skyhook_class_init (GeoclueSkyhookClass *klass) +{ + GcProviderClass *p_class = (GcProviderClass *)klass; + GObjectClass *o_class = (GObjectClass *)klass; + + p_class->shutdown = _shutdown; + p_class->get_status = geoclue_skyhook_get_status; + + o_class->finalize = geoclue_skyhook_finalize; +} + +static void +geoclue_skyhook_init (GeoclueSkyhook *skyhook) +{ + gc_provider_set_details (GC_PROVIDER (skyhook), + GEOCLUE_DBUS_SERVICE_SKYHOOK, + GEOCLUE_DBUS_PATH_SKYHOOK, + "Skyhook", "Skyhook.com based provider, uses gateway mac address to locate"); + skyhook->session = soup_session_sync_new (); + skyhook->conn = geoclue_connectivity_new (); +} + +static void +geoclue_skyhook_position_init (GcIfacePositionClass *iface) +{ + iface->get_position = geoclue_skyhook_get_position; +} + +int +main() +{ + g_type_init(); + g_thread_init (NULL); + + GeoclueSkyhook *o = g_object_new (GEOCLUE_TYPE_SKYHOOK, NULL); + o->loop = g_main_loop_new (NULL, TRUE); + + g_main_loop_run (o->loop); + + g_main_loop_unref (o->loop); + g_object_unref (o); + + return 0; +} diff --git a/.pc/tizen.patch/providers/skyhook/geoclue-skyhook.provider b/.pc/tizen.patch/providers/skyhook/geoclue-skyhook.provider new file mode 100755 index 0000000..1e0fcde --- /dev/null +++ b/.pc/tizen.patch/providers/skyhook/geoclue-skyhook.provider @@ -0,0 +1,8 @@ +[Geoclue Provider] +Name=Skyhook +Service=org.freedesktop.Geoclue.Providers.Skyhook +Path=/org/freedesktop/Geoclue/Providers/Skyhook +Accuracy=Street +Requires=RequiresNetwork +Provides=ProvidesCacheableOnConnection +Interfaces=org.freedesktop.Geoclue.Position |