+
+#define HOSTIP_LATITUDE_PATTERN "\"lat\":\""
+#define HOSTIP_LONGITUDE_PATTERN "\"lng\":\""
+#define HOSTIP_CITY_PATTERN "\"city\":\""
+#define HOSTIP_COUNTRY_PATTERN "\"country_name\":\""
+
+/**
+ * Automatic attempt to find out where you are using:
+ * 1. http://www.hostip.info ++
+ * 2. if not specific enough fallback to using the default goto tool with a country name
+ * ++ Using returned JSON information
+ * c.f. with googlesearch.c - similar implementation is used here
+ *
+ * returns:
+ * 0 if failed to locate anything
+ * 1 if exact latitude/longitude found
+ * 2 if position only as precise as a city
+ * 3 if position only as precise as a country
+ * @name: Contains the name of place found. Free this string after use.
+ */
+gint a_vik_goto_where_am_i ( VikViewport *vvp, struct LatLon *ll, gchar **name )
+{
+ gint result = 0;
+ *name = NULL;
+
+ gchar *tmpname = a_download_uri_to_tmp_file ( "http://api.hostip.info/get_json.php?position=true", NULL );
+ //gchar *tmpname = g_strdup ("../test/hostip2.json");
+ if (!tmpname) {
+ return result;
+ }
+
+ ll->lat = 0.0;
+ ll->lon = 0.0;
+
+ gchar *pat;
+ GMappedFile *mf;
+ gchar *ss;
+ gint fragment_len;
+
+ gchar lat_buf[32], lon_buf[32];
+ lat_buf[0] = lon_buf[0] = '\0';
+ gchar *country = NULL;
+ gchar *city = NULL;
+
+ if ((mf = g_mapped_file_new(tmpname, FALSE, NULL)) == NULL) {
+ g_critical(_("couldn't map temp file"));
+ goto tidy;
+ }
+
+ gsize len = g_mapped_file_get_length(mf);
+ gchar *text = g_mapped_file_get_contents(mf);
+
+ if ((pat = g_strstr_len(text, len, HOSTIP_COUNTRY_PATTERN))) {
+ pat += strlen(HOSTIP_COUNTRY_PATTERN);
+ fragment_len = 0;
+ ss = pat;
+ while (*pat != '"') {
+ fragment_len++;
+ pat++;
+ }
+ country = g_strndup(ss, fragment_len);
+ }
+
+ if ((pat = g_strstr_len(text, len, HOSTIP_CITY_PATTERN))) {
+ pat += strlen(HOSTIP_CITY_PATTERN);
+ fragment_len = 0;
+ ss = pat;
+ while (*pat != '"') {
+ fragment_len++;
+ pat++;
+ }
+ city = g_strndup(ss, fragment_len);
+ }
+
+ if ((pat = g_strstr_len(text, len, HOSTIP_LATITUDE_PATTERN))) {
+ pat += strlen(HOSTIP_LATITUDE_PATTERN);
+ ss = lat_buf;
+ if (*pat == '-')
+ *ss++ = *pat++;
+ while ((ss < (lat_buf + sizeof(lat_buf))) && (pat < (text + len)) &&
+ (g_ascii_isdigit(*pat) || (*pat == '.')))
+ *ss++ = *pat++;
+ *ss = '\0';
+ ll->lat = g_ascii_strtod(lat_buf, NULL);
+ }
+
+ if ((pat = g_strstr_len(text, len, HOSTIP_LONGITUDE_PATTERN))) {
+ pat += strlen(HOSTIP_LONGITUDE_PATTERN);
+ ss = lon_buf;
+ if (*pat == '-')
+ *ss++ = *pat++;
+ while ((ss < (lon_buf + sizeof(lon_buf))) && (pat < (text + len)) &&
+ (g_ascii_isdigit(*pat) || (*pat == '.')))
+ *ss++ = *pat++;
+ *ss = '\0';
+ ll->lon = g_ascii_strtod(lon_buf, NULL);
+ }
+
+ if ( ll->lat != 0.0 && ll->lon != 0.0 ) {
+ if ( ll->lat > -90.0 && ll->lat < 90.0 && ll->lon > -180.0 && ll->lon < 180.0 ) {
+ // Found a 'sensible' & 'precise' location
+ result = 1;
+ *name = g_strdup ( _("Locality") ); //Albeit maybe not known by an actual name!
+ }
+ }
+ else {
+ // Hopefully city name is unique enough to lookup position on
+ // Maybe for American places where hostip appends the State code on the end
+ // But if the country code is not appended if could easily get confused
+ // e.g. 'Portsmouth' could be at least
+ // Portsmouth, Hampshire, UK or
+ // Portsmouth, Viginia, USA.
+
+ // Try city name lookup
+ if ( city ) {
+ g_debug ( "%s: found city %s", __FUNCTION__, city );
+ if ( strcmp ( city, "(Unknown city)" ) != 0 ) {
+ VikCoord new_center;
+ if ( vik_goto_place ( NULL, vvp, city, &new_center ) ) {
+ // Got something
+ vik_coord_to_latlon ( &new_center, ll );
+ result = 2;
+ *name = city;
+ goto tidy;
+ }
+ }
+ }
+
+ // Try country name lookup
+ if ( country ) {
+ g_debug ( "%s: found country %s", __FUNCTION__, country );
+ if ( strcmp ( country, "(Unknown Country)" ) != 0 ) {
+ VikCoord new_center;
+ if ( vik_goto_place ( NULL, vvp, country, &new_center ) ) {
+ // Finally got something
+ vik_coord_to_latlon ( &new_center, ll );
+ result = 3;
+ *name = country;
+ goto tidy;
+ }
+ }
+ }
+ }
+
+ tidy:
+ g_mapped_file_unref ( mf );
+ (void)g_remove ( tmpname );
+ g_free ( tmpname );
+ return result;
+}