]>
Commit | Line | Data |
---|---|---|
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 |
44 | static void vik_goto_xml_tool_class_init ( VikGotoXmlToolClass *klass ); |
45 | static void vik_goto_xml_tool_init ( VikGotoXmlTool *vwd ); | |
51f93b0b | 46 | |
34e71b99 | 47 | static void vik_goto_xml_tool_finalize ( GObject *gob ); |
51f93b0b | 48 | |
34e71b99 | 49 | static int vik_goto_xml_tool_get_coord ( VikGotoTool *self, VikWindow *vw, VikViewport *vvp, gchar *srch_str, VikCoord *coord ); |
51f93b0b | 50 | |
34e71b99 | 51 | typedef struct _VikGotoXmlToolPrivate VikGotoXmlToolPrivate; |
51f93b0b | 52 | |
34e71b99 | 53 | struct _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 | 66 | GType 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 | ||
90 | enum | |
91 | { | |
92 | PROP_0, | |
93 | ||
94 | PROP_URL_FORMAT, | |
95 | PROP_LAT_PATH, | |
96 | PROP_LON_PATH, | |
97 | }; | |
98 | ||
99 | static void | |
34e71b99 | 100 | xml_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 | ||
132 | static void | |
34e71b99 | 133 | xml_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 | 162 | static 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 | 209 | VikGotoXmlTool *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 | 214 | static 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 | 225 | static void vik_goto_xml_tool_finalize ( GObject *gob ) |
51f93b0b GB |
226 | { |
227 | G_OBJECT_GET_CLASS(gob)->finalize(gob); | |
228 | } | |
229 | ||
230 | static gboolean | |
231 | stack_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 */ | |
261 | static 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 | ||
284 | static gboolean | |
34e71b99 | 285 | parse_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 | 336 | static 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 | ||
380 | done: | |
381 | g_free(escaped_srch_str); | |
382 | g_free(uri); | |
383 | g_remove(tmpname); | |
384 | g_free(tmpname); | |
385 | return ret; | |
386 | } |