]> git.street.me.uk Git - andy/viking.git/blame - src/vikgotoxmltool.c
Replace "search" substring by "goto"
[andy/viking.git] / src / vikgotoxmltool.c
CommitLineData
51f93b0b
GB
1/*
2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
3 *
4 * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
d260d798 5 * Copyright (C) 2009, Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
51f93b0b
GB
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 * Created by Quy Tonthat <qtonthat@gmail.com>
22 */
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26#include <stdlib.h>
27#include <stdio.h>
28#include <string.h>
bc9cecab
GB
29#ifdef HAVE_MATH_H
30#include "math.h"
31#endif
51f93b0b
GB
32#include <glib.h>
33#include <glib/gstdio.h>
34#include <glib/gprintf.h>
35#include <glib/gi18n.h>
36
37#include "viking.h"
38#include "util.h"
39#include "curl_download.h"
40
34e71b99 41#include "vikgotoxmltool.h"
51f93b0b
GB
42
43
34e71b99
GB
44static void vik_goto_xml_tool_class_init ( VikGotoXmlToolClass *klass );
45static void vik_goto_xml_tool_init ( VikGotoXmlTool *vwd );
51f93b0b 46
34e71b99 47static void vik_goto_xml_tool_finalize ( GObject *gob );
51f93b0b 48
34e71b99 49static int vik_goto_xml_tool_get_coord ( VikGotoTool *self, VikWindow *vw, VikViewport *vvp, gchar *srch_str, VikCoord *coord );
51f93b0b 50
34e71b99 51typedef struct _VikGotoXmlToolPrivate VikGotoXmlToolPrivate;
51f93b0b 52
34e71b99 53struct _VikGotoXmlToolPrivate
51f93b0b
GB
54{
55 gchar *url_format;
56 gchar *lat_path;
57 gchar *lon_path;
58
59 struct LatLon ll;
60};
61
34e71b99
GB
62#define GOTO_XML_TOOL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
63 VIK_GOTO_XML_TOOL_TYPE, \
64 VikGotoXmlToolPrivate))
51f93b0b 65
34e71b99 66GType vik_goto_xml_tool_get_type()
51f93b0b
GB
67{
68 static GType w_type = 0;
69
70 if (!w_type)
71 {
72 static const GTypeInfo w_info =
73 {
34e71b99 74 sizeof (VikGotoXmlToolClass),
51f93b0b
GB
75 NULL, /* base_init */
76 NULL, /* base_finalize */
34e71b99 77 (GClassInitFunc) vik_goto_xml_tool_class_init,
51f93b0b
GB
78 NULL, /* class_finalize */
79 NULL, /* class_data */
34e71b99 80 sizeof (VikGotoXmlTool),
51f93b0b 81 0,
34e71b99 82 (GInstanceInitFunc) vik_goto_xml_tool_init,
51f93b0b 83 };
34e71b99 84 w_type = g_type_register_static ( VIK_GOTO_TOOL_TYPE, "VikGotoXmlTool", &w_info, 0 );
51f93b0b
GB
85 }
86
87 return w_type;
88}
89
90enum
91{
92 PROP_0,
93
94 PROP_URL_FORMAT,
95 PROP_LAT_PATH,
96 PROP_LON_PATH,
97};
98
99static void
34e71b99 100xml_goto_tool_set_property (GObject *object,
51f93b0b
GB
101 guint property_id,
102 const GValue *value,
103 GParamSpec *pspec)
104{
34e71b99
GB
105 VikGotoXmlTool *self = VIK_GOTO_XML_TOOL (object);
106 VikGotoXmlToolPrivate *priv = GOTO_XML_TOOL_GET_PRIVATE (self);
51f93b0b
GB
107
108 switch (property_id)
109 {
110 case PROP_URL_FORMAT:
111 g_free (priv->url_format);
112 priv->url_format = g_value_dup_string (value);
113 break;
114
115 case PROP_LAT_PATH:
116 g_free (priv->lat_path);
117 priv->lat_path = g_value_dup_string (value);
118 break;
119
120 case PROP_LON_PATH:
121 g_free (priv->lon_path);
122 priv->lon_path = g_value_dup_string (value);
123 break;
124
125 default:
126 /* We don't have any other property... */
127 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
128 break;
129 }
130}
131
132static void
34e71b99 133xml_goto_tool_get_property (GObject *object,
51f93b0b
GB
134 guint property_id,
135 GValue *value,
136 GParamSpec *pspec)
137{
34e71b99
GB
138 VikGotoXmlTool *self = VIK_GOTO_XML_TOOL (object);
139 VikGotoXmlToolPrivate *priv = GOTO_XML_TOOL_GET_PRIVATE (self);
51f93b0b
GB
140
141 switch (property_id)
142 {
143 case PROP_URL_FORMAT:
144 g_value_set_string (value, priv->url_format);
145 break;
146
147 case PROP_LAT_PATH:
148 g_value_set_string (value, priv->lat_path);
149 break;
150
151 case PROP_LON_PATH:
152 g_value_set_string (value, priv->lon_path);
153 break;
154
155 default:
156 /* We don't have any other property... */
157 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
158 break;
159 }
160}
161
34e71b99 162static void vik_goto_xml_tool_class_init ( VikGotoXmlToolClass *klass )
51f93b0b
GB
163{
164 GObjectClass *object_class;
34e71b99 165 VikGotoToolClass *parent_class;
51f93b0b
GB
166 GParamSpec *pspec;
167
168 object_class = G_OBJECT_CLASS (klass);
169
34e71b99
GB
170 object_class->finalize = vik_goto_xml_tool_finalize;
171 object_class->set_property = xml_goto_tool_set_property;
172 object_class->get_property = xml_goto_tool_get_property;
51f93b0b
GB
173
174
175 pspec = g_param_spec_string ("url-format",
176 "URL format",
177 "The format of the URL",
178 "<no-set>" /* default value */,
179 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
180 g_object_class_install_property (object_class,
181 PROP_URL_FORMAT,
182 pspec);
183
184 pspec = g_param_spec_string ("lat-path",
185 "Lat path",
186 "XPath of the latitude",
187 "<no-set>" /* default value */,
188 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
189 g_object_class_install_property (object_class,
190 PROP_LAT_PATH,
191 pspec);
192
193 pspec = g_param_spec_string ("lon-path",
194 "Lon path",
195 "XPath of the longitude",
196 "<no-set>" /* default value */,
197 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
198 g_object_class_install_property (object_class,
199 PROP_LON_PATH,
200 pspec);
201
34e71b99 202 parent_class = VIK_GOTO_TOOL_CLASS (klass);
51f93b0b 203
34e71b99 204 parent_class->get_coord = vik_goto_xml_tool_get_coord;
51f93b0b 205
34e71b99 206 g_type_class_add_private (klass, sizeof (VikGotoXmlToolPrivate));
51f93b0b
GB
207}
208
34e71b99 209VikGotoXmlTool *vik_goto_xml_tool_new ()
51f93b0b 210{
34e71b99 211 return VIK_GOTO_XML_TOOL ( g_object_new ( VIK_GOTO_XML_TOOL_TYPE, "label", "Google", NULL ) );
51f93b0b
GB
212}
213
34e71b99 214static void vik_goto_xml_tool_init ( VikGotoXmlTool *self )
51f93b0b 215{
34e71b99 216 VikGotoXmlToolPrivate *priv = GOTO_XML_TOOL_GET_PRIVATE (self);
51f93b0b
GB
217 priv->url_format = NULL;
218 priv->lat_path = NULL;
219 priv->lon_path = NULL;
bc9cecab
GB
220 //
221 priv->ll.lat = NAN;
222 priv->ll.lon = NAN;
51f93b0b
GB
223}
224
34e71b99 225static void vik_goto_xml_tool_finalize ( GObject *gob )
51f93b0b
GB
226{
227 G_OBJECT_GET_CLASS(gob)->finalize(gob);
228}
229
230static gboolean
231stack_is_path (const GSList *stack,
232 const gchar *path)
233{
bc9cecab
GB
234 gboolean equal = TRUE;
235 int stack_len = g_list_length(stack);
236 int i = 0;
237 i = stack_len - 1;
238 while (equal == TRUE && i >= 0)
239 {
240 if (*path != '/')
241 equal = FALSE;
242 else
243 path++;
244 const gchar *current = g_list_nth_data(stack, i);
245 size_t len = strlen(current);
246 if (strncmp(path, current, len) != 0 )
247 equal = FALSE;
248 else
249 {
250 path += len;
251 }
252 i--;
253 }
254 if (*path != '\0')
255 equal = FALSE;
51f93b0b
GB
256 return equal;
257}
258
259/* Called for character data */
260/* text is not nul-terminated */
261static void
262_text (GMarkupParseContext *context,
263 const gchar *text,
264 gsize text_len,
265 gpointer user_data,
266 GError **error)
267{
34e71b99
GB
268 VikGotoXmlTool *self = VIK_GOTO_XML_TOOL (user_data);
269 VikGotoXmlToolPrivate *priv = GOTO_XML_TOOL_GET_PRIVATE (self);
51f93b0b 270 const GSList *stack = g_markup_parse_context_get_element_stack (context);
bc9cecab 271 gchar *textl = g_strndup(text, text_len);
039bdd14
GB
272 /* Store only first result */
273 if (isnan(priv->ll.lat) && stack_is_path (stack, priv->lat_path))
51f93b0b 274 {
bc9cecab 275 priv->ll.lat = g_ascii_strtod(textl, NULL);
51f93b0b 276 }
039bdd14 277 if (isnan(priv->ll.lon) && stack_is_path (stack, priv->lon_path))
51f93b0b 278 {
bc9cecab 279 priv->ll.lon = g_ascii_strtod(textl, NULL);
51f93b0b 280 }
bc9cecab 281 g_free(textl);
51f93b0b
GB
282}
283
284static gboolean
34e71b99 285parse_file_for_latlon(VikGotoXmlTool *self, gchar *filename, struct LatLon *ll)
51f93b0b
GB
286{
287 GMarkupParser xml_parser;
288 GMarkupParseContext *xml_context;
289 GError *error;
34e71b99 290 VikGotoXmlToolPrivate *priv = GOTO_XML_TOOL_GET_PRIVATE (self);
51f93b0b
GB
291
292 FILE *file = g_fopen (filename, "r");
293 if (file == NULL)
294 /* TODO emit warning */
295 return FALSE;
296
297 /* setup context parse (ie callbacks) */
298 xml_parser.start_element = NULL;
299 xml_parser.end_element = NULL;
300 xml_parser.text = &_text;
301 xml_parser.passthrough = NULL;
302 xml_parser.error = NULL;
303
304 xml_context = g_markup_parse_context_new(&xml_parser, 0, self, NULL);
bc9cecab
GB
305
306 /* setup result */
307 priv->ll.lat = NAN;
308 priv->ll.lon = NAN;
51f93b0b
GB
309
310 gchar buff[BUFSIZ];
311 size_t nb;
312 while ((nb = fread (buff, sizeof(gchar), BUFSIZ, file)) > 0)
313 {
314 if (!g_markup_parse_context_parse(xml_context, buff, nb, &error))
4ce0404a 315 fprintf(stderr, "%s: parsing error.\n", __FUNCTION__);
51f93b0b
GB
316 }
317 /* cleanup */
318 if (!g_markup_parse_context_end_parse(xml_context, &error))
4ce0404a 319 fprintf(stderr, "%s: errors occurred reading file.\n", __FUNCTION__);
51f93b0b
GB
320
321 g_markup_parse_context_free(xml_context);
322 fclose (file);
323
324 if (ll != NULL)
325 {
51f93b0b
GB
326 *ll = priv->ll;
327 }
328
bc9cecab
GB
329 if (isnan(priv->ll.lat) || isnan(priv->ll.lat))
330 /* At least one coordinate not found */
331 return FALSE;
332 else
333 return TRUE;
51f93b0b
GB
334}
335
34e71b99 336static int vik_goto_xml_tool_get_coord ( VikGotoTool *object, VikWindow *vw, VikViewport *vvp, gchar *srch_str, VikCoord *coord )
51f93b0b
GB
337{
338 FILE *tmp_file;
339 int tmp_fd;
340 gchar *tmpname;
341 gchar *uri;
342 gchar *escaped_srch_str;
343 int ret = 0; /* OK */
344 struct LatLon ll;
345
34e71b99 346 g_debug("%s: raw goto: %s", __FUNCTION__, srch_str);
51f93b0b
GB
347
348 escaped_srch_str = uri_escape(srch_str);
349
34e71b99 350 g_debug("%s: escaped goto: %s", __FUNCTION__, escaped_srch_str);
51f93b0b 351
34e71b99 352 if ((tmp_fd = g_file_open_tmp ("GOTO.XXXXXX", &tmpname, NULL)) == -1) {
51f93b0b
GB
353 g_critical(_("couldn't open temp file"));
354 exit(1);
355 }
356
34e71b99
GB
357 VikGotoXmlTool *self = VIK_GOTO_XML_TOOL (object);
358 VikGotoXmlToolPrivate *priv = GOTO_XML_TOOL_GET_PRIVATE (self);
51f93b0b
GB
359
360 tmp_file = fdopen(tmp_fd, "r+");
361 uri = g_strdup_printf(priv->url_format, escaped_srch_str);
362
363 /* TODO: curl may not be available */
364 if (curl_download_uri(uri, tmp_file, NULL)) { /* error */
365 fclose(tmp_file);
366 tmp_file = NULL;
367 ret = -1;
368 goto done;
369 }
370
371 fclose(tmp_file);
372 tmp_file = NULL;
bc9cecab 373 g_debug("%s: %s", __FILE__, tmpname);
51f93b0b
GB
374 if (!parse_file_for_latlon(self, tmpname, &ll)) {
375 ret = -1;
376 goto done;
377 }
51f93b0b
GB
378 vik_coord_load_from_latlon ( coord, vik_viewport_get_coord_mode(vvp), &ll );
379
380done:
381 g_free(escaped_srch_str);
382 g_free(uri);
383 g_remove(tmpname);
384 g_free(tmpname);
385 return ret;
386}