Fix #9777
This commit is contained in:
parent
4649256624
commit
0fe5a22bcc
3 changed files with 148 additions and 76 deletions
|
@ -1,93 +1,104 @@
|
|||
package net.osmand.osm.io;
|
||||
|
||||
|
||||
/**
|
||||
* @source http://www.javaworld.com/javaworld/javatips/jw-javatip47.html -- 24.11.2008, (mb)
|
||||
*/
|
||||
public class Base64 {
|
||||
/*******************************************************************************************************************
|
||||
* BASE 64 encoding of a String or an array of bytes. See also RFC 1421.
|
||||
*
|
||||
* @author Unknown
|
||||
* @author David W. Croft
|
||||
* @version 1998-06-08
|
||||
******************************************************************************************************************/
|
||||
/*******************************************************************************************************************
|
||||
* BASE 64 encoding of a String or an array of bytes. See also RFC 1421.
|
||||
*
|
||||
* @author Unknown
|
||||
* @author David W. Croft
|
||||
* @version 1998-06-08
|
||||
******************************************************************************************************************/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
public static final char[] alphabet = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 0 to 7
|
||||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 8 to 15
|
||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 16 to 23
|
||||
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', // 24 to 31
|
||||
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 32 to 39
|
||||
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', // 40 to 47
|
||||
'w', 'x', 'y', 'z', '0', '1', '2', '3', // 48 to 55
|
||||
'4', '5', '6', '7', '8', '9', '+', '/' }; // 56 to 63
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
public static final char[] alphabet = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 0 to 7
|
||||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 8 to 15
|
||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 16 to 23
|
||||
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', // 24 to 31
|
||||
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 32 to 39
|
||||
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', // 40 to 47
|
||||
'w', 'x', 'y', 'z', '0', '1', '2', '3', // 48 to 55
|
||||
'4', '5', '6', '7', '8', '9', '+', '/' }; // 56 to 63
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
public static String encode(final String s)
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
return encode(s.getBytes());
|
||||
}
|
||||
public static int indexOf(char c) {
|
||||
for (int i = 0; i < alphabet.length; i++) {
|
||||
if (alphabet[i] == c) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static String encode(final byte[] octetString)
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
int bits24;
|
||||
int bits6;
|
||||
|
||||
final char[] out = new char[((octetString.length - 1) / 3 + 1) * 4];
|
||||
public static String encode(final String s)
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
return encode(s.getBytes());
|
||||
}
|
||||
|
||||
int outIndex = 0;
|
||||
int i = 0;
|
||||
public static String encode(final byte[] octetString)
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
int bits24;
|
||||
int bits6;
|
||||
|
||||
while ((i + 3) <= octetString.length) {
|
||||
// store the octets
|
||||
bits24 = (octetString[i++] & 0xFF) << 16;
|
||||
bits24 |= (octetString[i++] & 0xFF) << 8;
|
||||
bits24 |= (octetString[i++] & 0xFF);
|
||||
final char[] out = new char[((octetString.length - 1) / 3 + 1) * 4];
|
||||
|
||||
bits6 = (bits24 & 0x00FC0000) >> 18;
|
||||
out[outIndex++] = alphabet[bits6];
|
||||
bits6 = (bits24 & 0x0003F000) >> 12;
|
||||
out[outIndex++] = alphabet[bits6];
|
||||
bits6 = (bits24 & 0x00000FC0) >> 6;
|
||||
out[outIndex++] = alphabet[bits6];
|
||||
bits6 = (bits24 & 0x0000003F);
|
||||
out[outIndex++] = alphabet[bits6];
|
||||
}
|
||||
int outIndex = 0;
|
||||
int i = 0;
|
||||
|
||||
if (octetString.length - i == 2) {
|
||||
// store the octets
|
||||
bits24 = (octetString[i] & 0xFF) << 16;
|
||||
bits24 |= (octetString[i + 1] & 0xFF) << 8;
|
||||
while ((i + 3) <= octetString.length) {
|
||||
// store the octets
|
||||
bits24 = (octetString[i++] & 0xFF) << 16;
|
||||
bits24 |= (octetString[i++] & 0xFF) << 8;
|
||||
bits24 |= (octetString[i++] & 0xFF);
|
||||
|
||||
bits6 = (bits24 & 0x00FC0000) >> 18;
|
||||
out[outIndex++] = alphabet[bits6];
|
||||
bits6 = (bits24 & 0x0003F000) >> 12;
|
||||
out[outIndex++] = alphabet[bits6];
|
||||
bits6 = (bits24 & 0x00000FC0) >> 6;
|
||||
out[outIndex++] = alphabet[bits6];
|
||||
bits6 = (bits24 & 0x00FC0000) >> 18;
|
||||
out[outIndex++] = alphabet[bits6];
|
||||
bits6 = (bits24 & 0x0003F000) >> 12;
|
||||
out[outIndex++] = alphabet[bits6];
|
||||
bits6 = (bits24 & 0x00000FC0) >> 6;
|
||||
out[outIndex++] = alphabet[bits6];
|
||||
bits6 = (bits24 & 0x0000003F);
|
||||
out[outIndex++] = alphabet[bits6];
|
||||
}
|
||||
|
||||
// padding
|
||||
out[outIndex++] = '=';
|
||||
} else if (octetString.length - i == 1) {
|
||||
// store the octets
|
||||
bits24 = (octetString[i] & 0xFF) << 16;
|
||||
if (octetString.length - i == 2) {
|
||||
// store the octets
|
||||
bits24 = (octetString[i] & 0xFF) << 16;
|
||||
bits24 |= (octetString[i + 1] & 0xFF) << 8;
|
||||
|
||||
bits6 = (bits24 & 0x00FC0000) >> 18;
|
||||
out[outIndex++] = alphabet[bits6];
|
||||
bits6 = (bits24 & 0x0003F000) >> 12;
|
||||
out[outIndex++] = alphabet[bits6];
|
||||
bits6 = (bits24 & 0x00FC0000) >> 18;
|
||||
out[outIndex++] = alphabet[bits6];
|
||||
bits6 = (bits24 & 0x0003F000) >> 12;
|
||||
out[outIndex++] = alphabet[bits6];
|
||||
bits6 = (bits24 & 0x00000FC0) >> 6;
|
||||
out[outIndex++] = alphabet[bits6];
|
||||
|
||||
// padding
|
||||
out[outIndex++] = '=';
|
||||
out[outIndex++] = '=';
|
||||
}
|
||||
// padding
|
||||
out[outIndex++] = '=';
|
||||
} else if (octetString.length - i == 1) {
|
||||
// store the octets
|
||||
bits24 = (octetString[i] & 0xFF) << 16;
|
||||
|
||||
return new String(out);
|
||||
}
|
||||
bits6 = (bits24 & 0x00FC0000) >> 18;
|
||||
out[outIndex++] = alphabet[bits6];
|
||||
bits6 = (bits24 & 0x0003F000) >> 12;
|
||||
out[outIndex++] = alphabet[bits6];
|
||||
|
||||
// padding
|
||||
out[outIndex++] = '=';
|
||||
out[outIndex++] = '=';
|
||||
}
|
||||
|
||||
return new String(out);
|
||||
}
|
||||
|
||||
}
|
|
@ -3,6 +3,8 @@ package net.osmand.util;
|
|||
import java.net.URI;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Locale;
|
||||
|
@ -11,6 +13,9 @@ import java.util.Set;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import net.osmand.data.LatLon;
|
||||
import net.osmand.util.GeoPointParserUtil.GeoParsedPoint;
|
||||
|
||||
public class GeoPointParserUtil {
|
||||
|
||||
|
||||
|
@ -69,6 +74,31 @@ public class GeoPointParserUtil {
|
|||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static int kMaxPointBytes = 10;
|
||||
private static int kMaxCoordBits = kMaxPointBytes * 3;
|
||||
public static LatLon decodeMapsMeLatLonToInt(String s) {
|
||||
// 44TvlEGXf-
|
||||
int lat = 0, lon = 0;
|
||||
int shift = kMaxCoordBits - 3;
|
||||
for (int i = 0; i < s.length(); ++i, shift -= 3) {
|
||||
int a = net.osmand.osm.io.Base64.indexOf(s.charAt(i));
|
||||
if (a < 0)
|
||||
return null;
|
||||
|
||||
int lat1 = (((a >> 5) & 1) << 2 | ((a >> 3) & 1) << 1 | ((a >> 1) & 1));
|
||||
int lon1 = (((a >> 4) & 1) << 2 | ((a >> 2) & 1) << 1 | (a & 1));
|
||||
lat |= lat1 << shift;
|
||||
lon |= lon1 << shift;
|
||||
}
|
||||
double middleOfSquare = 1 << (3 * (kMaxPointBytes - s.length()) - 1);
|
||||
lat += middleOfSquare;
|
||||
lon += middleOfSquare;
|
||||
|
||||
double dlat = ((double) lat) / ((1 << kMaxCoordBits) - 1) * 180 - 90;
|
||||
double dlon = ((double) lon) / ((1 << kMaxCoordBits) - 1 + 1) * 360.0 - 180;
|
||||
return new LatLon(dlat, dlon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses geo and map intents:
|
||||
|
@ -190,6 +220,31 @@ public class GeoPointParserUtil {
|
|||
int zoom = parseZoom(zm);
|
||||
return new GeoParsedPoint(lat, lon, zoom);
|
||||
}
|
||||
} else if (host.equals("ge0.me")) {
|
||||
// http:///44TvlEGXf-/Kyiv
|
||||
if (path.startsWith("/")) {
|
||||
path = path.substring(1);
|
||||
}
|
||||
String[] pms = path.split("/");
|
||||
String label = "";
|
||||
if (pms.length > 1) {
|
||||
label = pms[1];
|
||||
}
|
||||
String qry = pms[0];
|
||||
if (qry.length() < 10) {
|
||||
return null;
|
||||
}
|
||||
int indZoom = net.osmand.osm.io.Base64.indexOf(qry.charAt(0));
|
||||
int zoom = 15;
|
||||
if (indZoom >= 0) {
|
||||
zoom = indZoom / 4 + 4;
|
||||
}
|
||||
LatLon l = decodeMapsMeLatLonToInt(qry.substring(1).replace('-', '/'));
|
||||
if (l == null) {
|
||||
return null;
|
||||
}
|
||||
return new GeoParsedPoint(l.getLatitude(), l.getLongitude(), zoom, label);
|
||||
|
||||
} else if (simpleDomains.contains(host)) {
|
||||
if (uri.getQuery() == null && params.size() == 0) {
|
||||
// DOUBLE check this may be wrong test of openstreetmap.de (looks very weird url and server doesn't respond)
|
||||
|
@ -221,7 +276,6 @@ public class GeoPointParserUtil {
|
|||
String z = String.valueOf(GeoParsedPoint.NO_ZOOM);
|
||||
|
||||
if (params.containsKey("q")) {
|
||||
System.out.println("q=" + params.get("q"));
|
||||
Matcher matcher = commaSeparatedPairPattern.matcher(params.get("q"));
|
||||
if (matcher.matches()) {
|
||||
latString = matcher.group(1);
|
||||
|
|
|
@ -43,6 +43,13 @@ public class GeoPointParserUtilTest {
|
|||
"https://www.google.co.in/maps/place/data=!3m2!1e3!4b1!4m6!3m5!1s0x0:0x0!7e2!8m2!3d10.1213237!4d76.348392?shorturl=1");
|
||||
assertGeoPoint(actual, new GeoParsedPoint(10.1213237, 76.348392));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMapsMeParser() {
|
||||
GeoParsedPoint actual = GeoPointParserUtil.parse(
|
||||
"http://ge0.me/44TvlEGXf-/Kyiv");
|
||||
assertGeoPoint(actual, new GeoParsedPoint(50.45003, 30.52414, 18, "Kyiv"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeoPoint() {
|
||||
|
@ -449,21 +456,21 @@ public class GeoPointParserUtilTest {
|
|||
actual = GeoPointParserUtil.parse(url);
|
||||
assertGeoPoint(actual, new GeoParsedPoint("paris"));
|
||||
|
||||
// TODO this URL does not work, where is it used?
|
||||
// LEGACY this URL does not work, where is it used?
|
||||
// http://maps.google.com/maps/q=loc:34,-106&z=11
|
||||
url = "http://maps.google.com/maps/q=loc:" + ilat + "," + ilon + "&z=" + z;
|
||||
System.out.println("url: " + url);
|
||||
actual = GeoPointParserUtil.parse(url);
|
||||
assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z));
|
||||
|
||||
// TODO this URL does not work, where is it used?
|
||||
// LEGACY this URL does not work, where is it used?
|
||||
// http://maps.google.com/maps/q=loc:34.99393,-106.61568&z=11
|
||||
url = "http://maps.google.com/maps/q=loc:" + dlat + "," + dlon + "&z=" + z;
|
||||
System.out.println("url: " + url);
|
||||
actual = GeoPointParserUtil.parse(url);
|
||||
assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z));
|
||||
|
||||
// TODO this URL does not work, where is it used?
|
||||
// LEGACY this URL does not work, where is it used?
|
||||
// whatsapp
|
||||
// http://maps.google.com/maps/q=loc:34,-106 (You)
|
||||
z = GeoParsedPoint.NO_ZOOM;
|
||||
|
@ -472,7 +479,7 @@ public class GeoPointParserUtilTest {
|
|||
actual = GeoPointParserUtil.parse(url);
|
||||
assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z));
|
||||
|
||||
// TODO this URL does not work, where is it used?
|
||||
// LEGACY this URL does not work, where is it used?
|
||||
// whatsapp
|
||||
// http://maps.google.com/maps/q=loc:34.99393,-106.61568 (You)
|
||||
z = GeoParsedPoint.NO_ZOOM;
|
||||
|
|
Loading…
Reference in a new issue