Commit c9718de1 authored by Jussi Kukkonen's avatar Jussi Kukkonen

convert map_yahoo-backend to new GeoclueWebService

Includes small changes to GeoclueWebService to make it more
suitable for fetching binary data.
parent 15fd5eef
......@@ -95,7 +95,38 @@ geoclue_web_service_connection_events_deinit (GeoclueWebService *self) {}
#endif /* HAVE_LIBCONIC */
/* GFunc, use with g_list_foreach */
static void
geoclue_web_service_free_ns (gpointer data, gpointer user_data)
{
XmlNamespace *ns = (XmlNamespace *)data;
g_free (ns->name);
g_free (ns->uri);
g_free (ns);
}
/* GFunc, use with g_list_foreach */
static void
geoclue_web_service_register_ns (gpointer data, gpointer user_data)
{
g_assert (GEOCLUE_IS_WEB_SERVICE (user_data));
GeoclueWebService *self = (GeoclueWebService *)user_data;
XmlNamespace *ns = (XmlNamespace *)data;
xmlXPathRegisterNs (self->xpath_ctx,
(xmlChar*)ns->name, (xmlChar*)ns->uri);
}
/* Register namespaces listed in self->namespaces */
static void
geoclue_web_service_register_namespaces (GeoclueWebService *self)
{
g_assert (GEOCLUE_IS_WEB_SERVICE (self));
g_assert (self->xpath_ctx);
g_list_foreach (self->namespaces, (GFunc)geoclue_web_service_register_ns, self);
}
/* Parse data (self->response), build xpath context and register
* namespaces. Nothing will be done if xpath context exists already. */
static gboolean
geoclue_seb_service_build_xpath_context (GeoclueWebService *self)
{
......@@ -104,32 +135,44 @@ geoclue_seb_service_build_xpath_context (GeoclueWebService *self)
g_assert (GEOCLUE_IS_WEB_SERVICE (self));
g_assert (self->response);
xmlXPathFreeContext (self->xpath_ctx);
/* don't rebuild if there's no need */
if (self->xpath_ctx) {
return TRUE;
}
doc = xmlParseDoc ((xmlChar *)self->response);
/*make sure response is NULL-terminated*/
xmlChar *tmp = (xmlChar *)g_strndup(self->response, self->response_length);
g_debug ("parsing response: %s", tmp);
doc = xmlParseDoc (tmp);
if (!doc) {
/* TODO: error handling */
g_free (tmp);
return FALSE;
}
g_free (tmp);
self->xpath_ctx = xmlXPathNewContext(doc);
if (!self->xpath_ctx) {
/* TODO: error handling */
return FALSE;
}
geoclue_web_service_register_namespaces (self);
return TRUE;
}
/* fetch data from url, save into self->response */
static gboolean
geoclue_web_service_fetch (GeoclueWebService *self, gchar *url)
{
void* ctxt = NULL;
gint len;
gint retval=0;
xmlChar buf[1024];
xmlBuffer *output;
g_free (self->response);
xmlXPathFreeContext (self->xpath_ctx);
g_assert (url);
xmlNanoHTTPInit();
......@@ -144,17 +187,16 @@ geoclue_web_service_fetch (GeoclueWebService *self, gchar *url)
while ((len = xmlNanoHTTPRead (ctxt, buf, sizeof(buf))) > 0) {
if (xmlBufferAdd (output, buf, len) != 0) {
g_debug ("xmlBufferAdd failed.");
retval = -1;
break;
}
retval+=len;
}
xmlNanoHTTPClose(ctxt);
self->response = g_strdup ((gchar *) xmlBufferContent (output));
self->response_length = xmlBufferLength (output);
self->response = g_memdup (xmlBufferContent (output), self->response_length);
xmlBufferFree (output);
/* TODO: do I need retval (the length) for something later?? */
return (retval > 0);
return (self->response_length > 0);
}
static void
......@@ -166,6 +208,7 @@ geoclue_web_service_init (GTypeInstance *instance,
g_debug ("web_service init");
self->response = NULL;
self->response_length = 0;
self->xpath_ctx = NULL;
self->namespaces = NULL;
self->base_url = NULL;
......@@ -174,35 +217,6 @@ geoclue_web_service_init (GTypeInstance *instance,
geoclue_web_service_connection_events_init (self);
}
/* A GFunc, use with g_list_foreach */
static void
geoclue_web_service_free_ns (gpointer data, gpointer user_data)
{
XmlNamespace *ns = (XmlNamespace *)data;
g_free (ns->name);
g_free (ns->uri);
g_free (ns);
}
/* A GFunc, use with g_list_foreach */
static void
geoclue_web_service_register_ns (gpointer data, gpointer user_data)
{
g_assert (GEOCLUE_IS_WEB_SERVICE (user_data));
GeoclueWebService *self = (GeoclueWebService *)user_data;
XmlNamespace *ns = (XmlNamespace *)data;
xmlXPathRegisterNs (self->xpath_ctx,
(xmlChar*)ns->name, (xmlChar*)ns->uri);
}
static void
geoclue_web_service_register_namespaces (GeoclueWebService *self)
{
g_assert (GEOCLUE_IS_WEB_SERVICE (self));
g_assert (self->xpath_ctx);
g_list_foreach (self->namespaces, (GFunc)geoclue_web_service_register_ns, self);
}
static void
geoclue_web_service_finalize (GObject *obj)
......@@ -214,6 +228,7 @@ geoclue_web_service_finalize (GObject *obj)
geoclue_web_service_connection_events_deinit (self);
g_free (self->base_url);
g_free (self->response);
self->response_length = 0;
g_list_foreach (self->namespaces, (GFunc)geoclue_web_service_free_ns, NULL);
g_list_free (self->namespaces);
......@@ -230,6 +245,7 @@ enum {
GEOCLUE_WEB_SERVICE_URL = 1,
GEOCLUE_WEB_SERVICE_USING_CONNECTION_EVENTS,
GEOCLUE_WEB_SERVICE_RESPONSE,
GEOCLUE_WEB_SERVICE_RESPONSE_LENGTH,
};
static void
......@@ -245,6 +261,7 @@ geoclue_web_service_set_property (GObject *object,
case GEOCLUE_WEB_SERVICE_URL:
g_free (self->base_url);
g_free (self->response);
self->response_length = 0;
g_list_foreach (self->namespaces, (GFunc)geoclue_web_service_free_ns, NULL);
g_list_free (self->namespaces);
xmlXPathFreeContext (self->xpath_ctx);
......@@ -252,13 +269,11 @@ geoclue_web_service_set_property (GObject *object,
g_debug ("set base_url: %s\n",self->base_url);
break;
case GEOCLUE_WEB_SERVICE_USING_CONNECTION_EVENTS:
self->using_connection_events = g_value_get_boolean (value);
g_debug ("set using-connection-events: %s\n",self->using_connection_events ? "TRUE": "FALSE");
break;
g_assert_not_reached();
case GEOCLUE_WEB_SERVICE_RESPONSE:
self->response = g_value_dup_string (value);
g_debug ("set response: %s\n",self->response);
break;
g_assert_not_reached();
case GEOCLUE_WEB_SERVICE_RESPONSE_LENGTH:
g_assert_not_reached();
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
......@@ -273,6 +288,7 @@ geoclue_web_service_get_property (GObject *object,
{
g_return_if_fail (GEOCLUE_IS_WEB_SERVICE (object));
GeoclueWebService *self = (GeoclueWebService *) object;
gpointer copy;
switch (property_id) {
case GEOCLUE_WEB_SERVICE_URL:
......@@ -282,7 +298,11 @@ geoclue_web_service_get_property (GObject *object,
g_value_set_boolean (value, self->using_connection_events);
break;
case GEOCLUE_WEB_SERVICE_RESPONSE:
g_value_set_string (value, self->response);
copy = g_memdup (self->response, self->response_length);
g_value_set_pointer (value, copy);
break;
case GEOCLUE_WEB_SERVICE_RESPONSE_LENGTH:
g_value_set_int (value, self->response_length);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
......@@ -291,7 +311,7 @@ geoclue_web_service_get_property (GObject *object,
}
static void
connection_event_default_handler (GeoclueWebService *self, gboolean connected)
geoclue_web_service_connection_event_default_handler (GeoclueWebService *self, gboolean connected)
{
g_return_if_fail (GEOCLUE_IS_WEB_SERVICE (self));
g_debug ("connection event:%s connected", connected ? "" : " not");
......@@ -330,17 +350,25 @@ geoclue_web_service_class_init (gpointer klass,
GEOCLUE_WEB_SERVICE_USING_CONNECTION_EVENTS,
param_spec);
param_spec = g_param_spec_string ("response",
param_spec = g_param_spec_pointer ("response",
"response",
"Get the response of the last web service query",
NULL,
"Get copy of the response to the last web service query",
G_PARAM_READABLE);
g_object_class_install_property (gobject_class,
GEOCLUE_WEB_SERVICE_RESPONSE,
param_spec);
param_spec = g_param_spec_int ("response-length",
"response-length",
"Get the response length of the last web service query",
0, G_MAXINT, 0,
G_PARAM_READABLE);
g_object_class_install_property (gobject_class,
GEOCLUE_WEB_SERVICE_RESPONSE_LENGTH,
param_spec);
param_types[0] = G_TYPE_BOOLEAN;
web_service_class->connection_event = connection_event_default_handler;
web_service_class->connection_event = geoclue_web_service_connection_event_default_handler;
web_service_class->connection_event_signal_id =
g_signal_newv ("connection-event",
G_TYPE_FROM_CLASS (klass),
......@@ -418,11 +446,9 @@ geoclue_web_service_query (GeoclueWebService *self, ...)
}
g_assert (self->response);
g_free (url);
if (!geoclue_seb_service_build_xpath_context (self)) {
return FALSE;
}
g_assert (self->xpath_ctx);
geoclue_web_service_register_namespaces (self);
g_debug ("response length: %d", self->response_length);
return TRUE;
}
......@@ -438,14 +464,21 @@ geoclue_web_service_add_namespace (GeoclueWebService *self, gchar *namespace, gc
ns->uri = g_strdup (uri);
self->namespaces = g_list_prepend (self->namespaces, ns);
}
gboolean
geoclue_web_service_get_double (GeoclueWebService *self, gdouble *OUT_value, gchar *xpath)
{
g_return_val_if_fail (GEOCLUE_IS_WEB_SERVICE (self), FALSE);
g_return_val_if_fail (self->response, FALSE);
g_return_val_if_fail (OUT_value, FALSE);
g_return_val_if_fail (xpath, FALSE);
g_return_val_if_fail (self->xpath_ctx, FALSE);
/* parse the doc if not parsed yet and register namespaces */
if (!geoclue_seb_service_build_xpath_context (self)) {
return FALSE;
}
g_assert (self->xpath_ctx);
gboolean retval = FALSE;
xmlXPathObject *xpathObj = xmlXPathEvalExpression ((xmlChar*)xpath, self->xpath_ctx);
......@@ -463,10 +496,15 @@ gboolean
geoclue_web_service_get_string (GeoclueWebService *self, gchar **OUT_value, gchar* xpath)
{
g_return_val_if_fail (GEOCLUE_IS_WEB_SERVICE (self), FALSE);
g_return_val_if_fail (self->response, FALSE);
g_return_val_if_fail (OUT_value, FALSE);
g_return_val_if_fail (xpath, FALSE);
g_return_val_if_fail (self->xpath_ctx, FALSE);
/* parse the doc if not parsed yet and register namespaces */
if (!geoclue_seb_service_build_xpath_context (self)) {
return FALSE;
}
g_assert (self->xpath_ctx);
gboolean retval= FALSE;
xmlXPathObject *xpathObj = xmlXPathEvalExpression ((xmlChar*)xpath, self->xpath_ctx);
......@@ -477,6 +515,5 @@ geoclue_web_service_get_string (GeoclueWebService *self, gchar **OUT_value, gcha
}
xmlXPathFreeObject (xpathObj);
}
/*DEBUG*/
return retval;
}
......@@ -62,12 +62,12 @@
* }
*
* So, geoclue_web_service_query takes a NULL-terminated list of
* key-value pairs that will be appended to base_url. The value part
* will be escaped. The example case query url will be:
* key-value pairs that will be used as GET params. The value part
* of the pair will be escaped. The example case query url will be:
* "http://plazes.com/suggestions.xml?mac_address=00%3A11%3A95%3A20%3Adf%3A11"
*
* The actual response data is available (see "response"-property),
* but if the data is xml it's easier to use
* but if the data is xml it's a lot easier to use
* "geoclue_web_service_get_*" -methods to get specific data using
* simple xpath expressions.
*
......@@ -116,7 +116,8 @@ struct _GeoclueWebService {
/* private */
gchar* base_url;
gchar *response;
guchar *response;
gint response_length;
GList *namespaces;
gboolean using_connection_events;
xmlXPathContext *xpath_ctx;
......
......@@ -19,7 +19,7 @@ $(service_DATA): $(service_in_files) Makefile
AM_CPPFLAGS = $(YAHOO_CFLAGS) -I$(top_srcdir)
AM_LDFLAGS = $(YAHOO_LIBS)
AM_LDFLAGS = $(YAHOO_LIBS) ../common/geoclue_web_service.o
EXTRA_DIST = \
geoclue_map_server_yahoo.h \
......
......@@ -21,7 +21,7 @@
#include <geoclue_map_signal_marshal.h>
#include <dbus/dbus-glib-bindings.h>
#include <math.h>
typedef enum _geoclue_map_returncode
{
......@@ -41,14 +41,7 @@ typedef enum _geoclue_map_returncode
} GEOCLUE_MAP_RETURNCODE;
#include <libxml/xmlreader.h>
#include <libsoup/soup.h>
#include <fcntl.h>
#include <stdlib.h>
#include <math.h>
#define YAHOO_MAP_URL "http://api.local.yahoo.com/MapsService/V1/mapImage"
#define GEOCLUE_MAP_MIN_HEIGHT 100
#define GEOCLUE_MAP_MAX_HEIGHT 2000
......@@ -127,17 +120,19 @@ geoclue_map_init (GeoclueMap *obj)
{
g_printerr("Unable to register Geoclue map service: %s", error->message);
g_error_free (error);
exit(1);
}
if (request_ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
{
g_printerr("Yahoo maps service already running!\n");
}
g_print("registered mapping interface \n");
exit(1);
}
if (request_ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
{
g_printerr("Yahoo maps service already running!\n");
}
obj->web_service = g_object_new (GEOCLUE_TYPE_WEB_SERVICE,
"base_url", YAHOO_MAP_URL,
NULL);
g_print("registered mapping interface \n");
}
......@@ -239,114 +234,68 @@ gboolean geoclue_map_min_width(GeoclueMap *obj, int* min_width, GError **error)
void geoclue_map_map_thread(params *obj)
{
gdouble IN_latitude = obj->IN_latitude;
gdouble IN_longitude = obj->IN_longitude;
gint IN_width = obj->IN_width;
gint IN_height = obj->IN_height;
gint IN_zoom = obj->IN_zoom;
SoupSession *session;
SoupMessage *msg;
SoupMessage *msg2;
const char *cafile = NULL;
SoupUri *proxy = NULL;
SoupUri *base_uri = NULL;
base_uri = soup_uri_new ("http://api.local.yahoo.com/MapsService/V1/mapImage?appid=libgeomap&latitude=38.0&longitude=-122.0&imagetype=png&image_height=800&image_width=800&zoom=7");
char* proxy_env;
proxy_env = getenv ("http_proxy");
printf("found proxy %s:end\n", proxy_env);
if (proxy_env != NULL) {
printf("added proxy %s\n", proxy_env);
proxy = soup_uri_new (proxy_env);
session = soup_session_sync_new_with_options (
SOUP_SESSION_SSL_CA_FILE, cafile,
SOUP_SESSION_PROXY_URI, proxy,
NULL);
gchar *lat = g_strdup_printf ("%f", obj->IN_latitude);
gchar *lon = g_strdup_printf ("%f", obj->IN_longitude);
gchar *width = g_strdup_printf ("%d", obj->IN_width);
gchar *height = g_strdup_printf ("%d", obj->IN_height);
gchar *zoom = g_strdup_printf ("%d", obj->IN_zoom);
gchar *png_url;
GeoclueWebService *png_service;
if (!geoclue_web_service_query (obj->server->web_service,
"appid", "YahooDemo",
"latitude", lat,
"longitude", lon,
"imagetype", "png",
"image_height", height,
"image_width", width,
"zoom", zoom,
NULL)) {
/* TODO: error handling */
return;
}
else
{
session = soup_session_sync_new ();
g_free (lat);
g_free (lon);
g_free (width);
g_free (height);
g_free (zoom);
geoclue_web_service_get_string (obj->server->web_service,
&png_url, "//Result");
if (!g_str_has_prefix (png_url, "http://")) {
/* TODO: error handling */
return;
}
g_debug("Trying to grab image %s\n", png_url);
png_service = g_object_new (GEOCLUE_TYPE_WEB_SERVICE,
"base_url",png_url,
NULL);
g_free (png_url);
char url[5000];
snprintf(url, 5000,"http://api.local.yahoo.com/MapsService/V1/mapImage?appid=YahooDemo&latitude=%f&longitude=%f&imagetype=png&image_height=%d&image_width=%d&zoom=%d", IN_latitude, IN_longitude, IN_height, IN_width, IN_zoom);
g_print(url);
msg = soup_message_new ("GET", url);
soup_session_send_message(session, msg);
char *name, *value;
xmlTextReaderPtr reader;
int ret;
char* pngurl;
//reader = xmlReaderForFile(argv[1], NULL, 0);
reader = xmlReaderForMemory (msg->response.body,
msg->response.length,
NULL,
NULL,
0);
ret = xmlTextReaderRead(reader);
//FIXME: super hack because I don't know how to use the XML libraries. This just works for now
while (ret == 1) {
name = (char*)xmlTextReaderConstName(reader);
if (!strcmp(name,"#text"))
{
value = (char*)xmlTextReaderConstValue(reader);
printf("%s %s\n", name, value);
int size = strlen(value);
pngurl = malloc(size);
strcpy(pngurl, value);
}
ret = xmlTextReaderRead(reader);
if (!geoclue_web_service_query (png_service, NULL)) {
/* TODO: error handling */
return;
}
xmlFreeTextReader(reader);
GArray *mydata;
mydata = g_array_new (FALSE, FALSE, sizeof (guint8));
g_object_get (png_service,
"response", &mydata->data,
"response-length", &mydata->len,
NULL);
g_debug ("map size: %d", mydata->len);
// A very bad rough sanity check
if(pngurl != NULL)
{
if(pngurl[0] == 'h')
{
printf("Trying to grab image %s\n", pngurl);
msg2 = soup_message_new ("GET", pngurl);
soup_session_send_message(session, msg2);
printf("got message\n, parsing\n");
GArray *mydata;
mydata = g_array_new(FALSE,FALSE, sizeof(guint8));
mydata->data = msg2->response.body;
mydata->len = msg2->response.length;
g_object_unref (png_service);
g_signal_emit_by_name (obj->server,
"get_map_finished",
0, mydata, "image/png");
}
}
g_signal_emit_by_name (obj->server,
"get_map_finished",
0, mydata, "image/png");
};
gboolean geoclue_map_get_map (GeoclueMap *obj, const gdouble IN_latitude, const gdouble IN_longitude, const gint IN_width, const gint IN_height, const gint IN_zoom, int* return_code, GError **error)
{
......@@ -500,6 +449,7 @@ gboolean geoclue_map_service_available(GeoclueMap *obj, gboolean* OUT_available,
gboolean geoclue_map_shutdown(GeoclueMap *obj, GError** error)
{
g_object_unref (obj->web_service);
g_main_loop_quit (obj->loop);
return TRUE;
}
......
......@@ -19,14 +19,10 @@
#ifndef __GEOCLUE_MAP_SERVER_H__
#define __GEOCLUE_MAP_SERVER_H__
#define DBUS_API_SUBJECT_TO_CHANGE
#include <dbus/dbus-glib.h>
#include <glib.h>
#include <stdio.h>
#include <string.h>
#include <config.h>
#include <glib.h>
#include <dbus/dbus-glib.h>
#include "../common/geoclue_web_service.h"
#define GEOCLUE_MAP_DBUS_SERVICE "org.freedesktop.geoclue.map.yahoo"
#define GEOCLUE_MAP_DBUS_PATH "/org/freedesktop/geoclue/map/yahoo"
......@@ -34,11 +30,8 @@
G_BEGIN_DECLS
//Let's create a geoclue_map object that has one method of geoclue_map
typedef struct GeoclueMap GeoclueMap;
typedef struct GeoclueMapClass GeoclueMapClass;
......@@ -46,17 +39,16 @@ GType geoclue_map_get_type (void);
struct GeoclueMap
{
GObject parent;
GMainLoop* loop;
GeoclueWebService *web_service;
char* buffer;
GArray* OUT_map_buffer;
gint width;
gint height;
gboolean pending_request;
GMainLoop* loop;
};
struct GeoclueMapClass
......@@ -94,11 +86,8 @@ gboolean geoclue_map_service_available(GeoclueMap *obj, gboolean* OUT_available,
gboolean geoclue_map_shutdown(GeoclueMap *obj, GError** error);
G_END_DECLS
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment