Fix osmo bugs: use https, encryption, cancel
Conflicts: OsmAnd/res/values/strings.xml
This commit is contained in:
parent
46173129f0
commit
9963f41ccc
13 changed files with 168 additions and 28 deletions
|
@ -84,6 +84,7 @@
|
|||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dip"
|
||||
android:autoLink="web"
|
||||
android:gravity="center"
|
||||
android:textSize="18sp" />
|
||||
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dip"
|
||||
android:autoLink="web"
|
||||
android:gravity="center"
|
||||
android:textSize="18sp" />
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources><string name="srtm_plugin_description">Плагин позволяет загружать контурные линии и затемнение высот для использования оффлайн (\"Настройки\" → \"Управление файлами карт\" → \"Загрузить\").</string>
|
||||
<resources>
|
||||
<string name="osmo_use_https_descr">Использовать безопасное соединение с сервером</string>
|
||||
<string name="osmo_use_https">Использовать https</string>
|
||||
<string name="srtm_plugin_description">Плагин позволяет загружать контурные линии и затемнение высот для использования оффлайн (\"Настройки\" → \"Управление файлами карт\" → \"Загрузить\").</string>
|
||||
<string name="srtm_paid_version_msg">Рассмотрите, пожалуйста, покупку плагина \"Линии высот\" в Google Play, чтобы поддержать последующую разработку.</string>
|
||||
<string name="srtm_paid_version_title">Линии высот</string>
|
||||
<string name="av_def_action_video">Запись видео</string>
|
||||
|
|
|
@ -9,6 +9,13 @@
|
|||
3. All your modified/created strings are in the top of the file (to make easier find what\'s translated).
|
||||
PLEASE: Have a look at http://code.google.com/p/osmand/wiki/UIConsistency, it may really improve your and our work :-) Thx - Hardy
|
||||
-->
|
||||
<string name="osmo_use_https_descr">Use secure connection with server</string>
|
||||
<string name="osmo_use_https">Use https</string>
|
||||
<string name="advanced_settings">Advanced</string>
|
||||
<string name="rendering_attr_publicTransportMode_name">Bus, trolleybus, shuttle routes</string>
|
||||
<string name="rendering_attr_tramTrainRoutes_name">Tram and train routes</string>
|
||||
<string name="rendering_attr_subwayMode_name">Subway routes</string>
|
||||
<string name="lock_screen_request_explanation">%1$s needs this permission to turn off the screen for the power saving feature.</string>
|
||||
<string name="wake_on_voice">Turn on the screen</string>
|
||||
<string name="wake_on_voice_descr">Turn on the phone screen when approaching a turn</string>
|
||||
<string name="select_impassable_road">Select on map</string>
|
||||
|
|
|
@ -57,6 +57,8 @@ public class OsmandSettings {
|
|||
void addListener(StateChangedListener<T> listener);
|
||||
|
||||
void removeListener(StateChangedListener<T> listener);
|
||||
|
||||
boolean isSet();
|
||||
}
|
||||
|
||||
private abstract class PreferenceWithListener<T> implements OsmandPreference<T> {
|
||||
|
@ -168,6 +170,11 @@ public class OsmandSettings {
|
|||
set(ApplicationMode.DEFAULT);
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean isSet() {
|
||||
return true;
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean set(ApplicationMode val) {
|
||||
ApplicationMode oldMode = currentMode;
|
||||
|
@ -875,6 +882,9 @@ public class OsmandSettings {
|
|||
|
||||
public final OsmandPreference<Boolean> OSMO_AUTO_CONNECT = new BooleanPreference("osmo_automatically_connect", false).makeGlobal();
|
||||
|
||||
public final CommonPreference<Boolean> OSMO_USE_HTTPS = new BooleanPreference("osmo_use_https",
|
||||
Build.VERSION.SDK_INT < 14/*Build.VERSION_CODES.ICE_CREAM_SANDWICH*/? false : true).makeGlobal();
|
||||
|
||||
public final OsmandPreference<Long> OSMO_LAST_PING = new LongPreference("osmo_last_ping", 0).makeGlobal().cache();
|
||||
|
||||
public final OsmandPreference<Boolean> OSMO_AUTO_SEND_LOCATIONS = new BooleanPreference("osmo_automatically_send_locations", false).makeGlobal();
|
||||
|
|
|
@ -287,6 +287,9 @@ public class OsMoGroups implements OsMoReactor, OsmoTrackerListener {
|
|||
if (!mid.equals(trackerId)) {
|
||||
if (toDelete.contains(trackerId)) {
|
||||
toDelete.remove(trackerId);
|
||||
OsMoDevice dv = mainGroup.users.get(trackerId);
|
||||
dv.serverColor = device.userColor;
|
||||
dv.serverName = device.userName;
|
||||
} else {
|
||||
mainGroup.users.put(trackerId, device);
|
||||
}
|
||||
|
@ -478,7 +481,9 @@ public class OsMoGroups implements OsMoReactor, OsmoTrackerListener {
|
|||
}
|
||||
points.add(pt);
|
||||
}
|
||||
plugin.getSaveGpxTask(gr.groupId + "_points", modify).execute(points.toArray(new WptPt[points.size()]));
|
||||
if(points.size() > 0) {
|
||||
plugin.getSaveGpxTask(gr.name + " points", modify, false).execute(points.toArray(new WptPt[points.size()]));
|
||||
}
|
||||
}
|
||||
if(deleteUsers) {
|
||||
for(OsMoDevice s : toDelete.values()) {
|
||||
|
|
|
@ -241,8 +241,11 @@ public class OsMoGroupsActivity extends OsmandExpandableListActivity implements
|
|||
mtd.setVisibility(visible? View.VISIBLE:View.GONE);
|
||||
if(visible) {
|
||||
mtd.setText(si.motd);
|
||||
mtd.setLinksClickable(true);
|
||||
mtd.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
}
|
||||
|
||||
|
||||
CompoundButton login = (CompoundButton) header.findViewById(R.id.osmo_login_logoff);
|
||||
login.setChecked(osMoPlugin.getService().isLoggedIn());
|
||||
login.setOnCheckedChangeListener(new LoginOnCheckedChangeListener());
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
package net.osmand.plus.osmo;
|
||||
|
||||
import java.security.acl.Group;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -75,6 +73,7 @@ public class OsMoGroupsStorage {
|
|||
public void load() {
|
||||
String grp = pref.get();
|
||||
try {
|
||||
System.out.println("DEBUG : OsMo groups load info " + grp);
|
||||
JSONObject obj = new JSONObject(grp);
|
||||
parseGroupUsers(mainGroup, obj);
|
||||
if(!obj.has(GROUPS)) {
|
||||
|
|
|
@ -67,12 +67,12 @@ public class OsMoPlugin extends OsmandPlugin implements MonitoringInfoControlSer
|
|||
|
||||
|
||||
public OsMoPlugin(final OsmandApplication app) {
|
||||
this.app = app;
|
||||
service = new OsMoService(app, this);
|
||||
tracker = new OsMoTracker(service, app.getSettings().OSMO_SAVE_TRACK_INTERVAL,
|
||||
app.getSettings().OSMO_AUTO_SEND_LOCATIONS);
|
||||
new OsMoControlDevice(app, this, service, tracker);
|
||||
groups = new OsMoGroups(this, service, tracker, app);
|
||||
this.app = app;
|
||||
ApplicationMode.regWidget("osmo_control", (ApplicationMode[])null);
|
||||
}
|
||||
|
||||
|
@ -85,6 +85,7 @@ public class OsMoPlugin extends OsmandPlugin implements MonitoringInfoControlSer
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
public OsMoGroupsActivity getGroupsActivity() {
|
||||
return groupsActivity;
|
||||
}
|
||||
|
@ -229,8 +230,17 @@ public class OsMoPlugin extends OsmandPlugin implements MonitoringInfoControlSer
|
|||
if (si != null) {
|
||||
String uname = si.username;
|
||||
if (uname != null && uname.length() > 0) {
|
||||
if (uname.length() > 7 && uname.indexOf(' ') != -1) {
|
||||
uname = uname.substring(0, uname.indexOf(' '));
|
||||
if (uname.length() > 7) {
|
||||
for(int k = 4; k < uname.length(); k++) {
|
||||
if(!Character.isLetterOrDigit(uname.charAt(k)) &&
|
||||
uname.charAt(k) != '.' && uname.charAt(k) != '-') {
|
||||
uname = uname.substring(0, k);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(uname.length() > 12) {
|
||||
uname = uname.substring(0, 12);
|
||||
}
|
||||
}
|
||||
if (uname.length() > 4) {
|
||||
txt = "";
|
||||
|
@ -350,11 +360,11 @@ public class OsMoPlugin extends OsmandPlugin implements MonitoringInfoControlSer
|
|||
return service;
|
||||
}
|
||||
|
||||
public AsyncTask<WptPt, String, String> getSaveGpxTask(final String name, final long timestamp) {
|
||||
public AsyncTask<WptPt, String, String> getSaveGpxTask(final String name, final long timestamp, final boolean generateToast) {
|
||||
return new AsyncTask<WptPt, String, String>() {
|
||||
|
||||
protected void onProgressUpdate(String... values) {
|
||||
if (values != null) {
|
||||
if (values != null && generateToast) {
|
||||
String t = "";
|
||||
for (String s : values) {
|
||||
t += s + "\n";
|
||||
|
@ -381,8 +391,10 @@ public class OsMoPlugin extends OsmandPlugin implements MonitoringInfoControlSer
|
|||
if (errors == null) {
|
||||
errors = "";
|
||||
}
|
||||
if(generateToast) {
|
||||
publishProgress(app.getString(R.string.osmo_gpx_points_downloaded, name));
|
||||
}
|
||||
}
|
||||
SelectedGpxFile byPath = app.getSelectedGpxHelper().getSelectedFileByPath(ps.getAbsolutePath());
|
||||
if (byPath == null || changed) {
|
||||
GPXFile selectGPXFile = GPXUtilities.loadGPXFile(app, ps);
|
||||
|
@ -396,7 +408,7 @@ public class OsMoPlugin extends OsmandPlugin implements MonitoringInfoControlSer
|
|||
|
||||
@Override
|
||||
protected void onPostExecute(String result) {
|
||||
if (result.length() > 0) {
|
||||
if (result.length() > 0 && generateToast) {
|
||||
app.showToastMessage(app.getString(R.string.osmo_io_error) + result);
|
||||
}
|
||||
}
|
||||
|
@ -525,4 +537,8 @@ public class OsMoPlugin extends OsmandPlugin implements MonitoringInfoControlSer
|
|||
}
|
||||
}
|
||||
|
||||
public boolean useHttps() {
|
||||
return app.getSettings().OSMO_USE_HTTPS.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
|||
|
||||
import net.osmand.Location;
|
||||
import net.osmand.access.AccessibleToast;
|
||||
import net.osmand.core.jni.ColorARGB;
|
||||
import net.osmand.data.LatLon;
|
||||
import net.osmand.data.RotatedTileBox;
|
||||
import net.osmand.plus.OsmAndFormatter;
|
||||
|
@ -294,6 +293,7 @@ public class OsMoPositionLayer extends OsmandMapLayer implements ContextMenuLaye
|
|||
private static String followTrackerId;
|
||||
private static LatLon followMapLocation;
|
||||
private static String followDestinationId;
|
||||
private static LatLon followTargetLocation;
|
||||
|
||||
public static void setFollowTrackerId(OsMoDevice d) {
|
||||
if(d != null) {
|
||||
|
@ -322,6 +322,18 @@ public class OsMoPositionLayer extends OsmandMapLayer implements ContextMenuLaye
|
|||
Location l = device.getLastLocation();
|
||||
if(sameDestId && l != null) {
|
||||
TargetPointsHelper targets = map.getMyApplication().getTargetPointsHelper();
|
||||
final TargetPoint pn = targets.getPointToNavigate();
|
||||
LatLon lt = new LatLon(l.getLatitude(), l.getLongitude());
|
||||
boolean cancelDestinationId = false;
|
||||
if(followTargetLocation != null ) {
|
||||
if(pn == null || pn.point == null || !pn.point.equals(lt) ) {
|
||||
cancelDestinationId = true;
|
||||
}
|
||||
}
|
||||
if(cancelDestinationId) {
|
||||
followTargetLocation = null;
|
||||
followDestinationId = null;
|
||||
} else {
|
||||
RoutingHelper rh = map.getMyApplication().getRoutingHelper();
|
||||
double dist = 1;
|
||||
if (rh.isRouteBeingCalculated()) {
|
||||
|
@ -329,12 +341,12 @@ public class OsMoPositionLayer extends OsmandMapLayer implements ContextMenuLaye
|
|||
} else if (rh.isRouteCalculated()) {
|
||||
dist = 30;
|
||||
}
|
||||
LatLon lt = new LatLon(l.getLatitude(), l.getLongitude());
|
||||
final TargetPoint pn = targets.getPointToNavigate();
|
||||
if (pn == null || MapUtils.getDistance(pn.point, lt) > dist) {
|
||||
followTargetLocation = lt;
|
||||
targets.navigateToPoint(lt, true, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean sameId = Algorithms.objectEquals(followTrackerId, device.trackerId);
|
||||
if(sameId && !schedule && l != null) {
|
||||
|
|
|
@ -4,11 +4,20 @@ import java.io.BufferedReader;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.math.BigInteger;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.PublicKey;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.security.spec.RSAPublicKeySpec;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
|
@ -45,6 +54,12 @@ import android.support.v4.app.NotificationCompat;
|
|||
import android.text.TextUtils;
|
||||
|
||||
public class OsMoService implements OsMoReactor {
|
||||
private static final String HTTP_API_PREPARE = "http://api.osmo.mobi/prepare";
|
||||
private static final String HTTPS_API_PREPARE = "https://api.osmo.mobi/prepare";
|
||||
private static final String HTTP_AUTH = "http://api.osmo.mobi/auth";
|
||||
private static final String HTTPS_AUTH = "https://api.osmo.mobi/auth";
|
||||
private static final boolean USE_RSA_ENCRYPTION = false;
|
||||
|
||||
public static final String REGENERATE_CMD = "TRACKER_REGENERATE_ID";
|
||||
public static final String SIGN_IN_URL = "http://osmo.mobi/signin?key=";
|
||||
private OsMoThread thread;
|
||||
|
@ -61,6 +76,7 @@ public class OsMoService implements OsMoReactor {
|
|||
private boolean enabled = false;
|
||||
private BroadcastReceiver broadcastReceiver;
|
||||
private Notification notification;
|
||||
|
||||
public final static String OSMO_REGISTER_AGAIN = "OSMO_REGISTER_AGAIN"; //$NON-NLS-1$
|
||||
private final static int SIMPLE_NOTFICATION_ID = 5;
|
||||
|
||||
|
@ -170,7 +186,7 @@ public class OsMoService implements OsMoReactor {
|
|||
|
||||
public String registerOsmoDeviceKey() throws IOException {
|
||||
HttpClient httpclient = new DefaultHttpClient();
|
||||
HttpPost httppost = new HttpPost("http://api.osmo.mobi/auth");
|
||||
HttpPost httppost = new HttpPost(plugin.useHttps()? HTTPS_AUTH : HTTP_AUTH);
|
||||
try {
|
||||
// Add your data
|
||||
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
|
||||
|
@ -209,6 +225,7 @@ public class OsMoService implements OsMoReactor {
|
|||
public String token;
|
||||
public String uid;
|
||||
public String username;
|
||||
|
||||
// after auth
|
||||
public String protocol = "";
|
||||
public String groupTrackerId;
|
||||
|
@ -217,6 +234,8 @@ public class OsMoService implements OsMoReactor {
|
|||
public long motdTimestamp;
|
||||
|
||||
public String motd = "";
|
||||
public Cipher clientEncCypher;
|
||||
public Cipher clientDecCypher;
|
||||
}
|
||||
|
||||
public SessionInfo getCurrentSessionInfo() {
|
||||
|
@ -258,12 +277,33 @@ public class OsMoService implements OsMoReactor {
|
|||
deviceKey = registerOsmoDeviceKey();
|
||||
}
|
||||
HttpClient httpclient = new DefaultHttpClient();
|
||||
HttpPost httppost = new HttpPost("http://api.osmo.mobi/prepare");
|
||||
KeyPair getMsgPair = null;
|
||||
if (plugin.useHttps() && USE_RSA_ENCRYPTION) {
|
||||
try {
|
||||
KeyPairGenerator rsaGen = KeyPairGenerator.getInstance("RSA");
|
||||
getMsgPair = rsaGen.generateKeyPair();
|
||||
} catch (Exception e1) {
|
||||
if (thread != null) {
|
||||
thread.exc("Private key can't be generated", e1);
|
||||
} else {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
HttpPost httppost = new HttpPost(plugin.useHttps()? HTTPS_API_PREPARE : HTTP_API_PREPARE);
|
||||
try {
|
||||
// Add your data
|
||||
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
|
||||
nameValuePairs.add(new BasicNameValuePair("app", Version.getFullVersion(app)));
|
||||
nameValuePairs.add(new BasicNameValuePair("key", deviceKey));
|
||||
if(getMsgPair != null && getMsgPair.getPublic() instanceof RSAPublicKey) {
|
||||
nameValuePairs.add(new BasicNameValuePair("encAlgorithm", "RSA"));
|
||||
BigInteger modulus = ((RSAPublicKey) getMsgPair.getPublic()).getModulus();
|
||||
BigInteger pe = ((RSAPublicKey) getMsgPair.getPublic()).getPublicExponent();
|
||||
nameValuePairs.add(new BasicNameValuePair("encClientPublicKey1", modulus.toString()));
|
||||
nameValuePairs.add(new BasicNameValuePair("encClientPublicKey2", pe.toString()));
|
||||
}
|
||||
|
||||
if(app.getSettings().OSMO_USER_PWD.get() != null) {
|
||||
nameValuePairs.add(new BasicNameValuePair("auth", app.getSettings().OSMO_USER_PWD.get()));
|
||||
}
|
||||
|
@ -304,6 +344,23 @@ public class OsMoService implements OsMoReactor {
|
|||
si.hostName = a.substring(0, i);
|
||||
si.port = a.substring(i + 1);
|
||||
si.token = obj.getString("token");
|
||||
try {
|
||||
if(getMsgPair != null && obj.has("encServerPublicKey1")) {
|
||||
si.clientEncCypher = Cipher.getInstance("RSA");
|
||||
PublicKey pk = KeyFactory.getInstance("RSA").generatePublic(new RSAPublicKeySpec(new BigInteger(obj.getString("encServerPublicKey1")),
|
||||
new BigInteger(obj.getString("encServerPublicKey2"))));
|
||||
si.clientEncCypher.init(Cipher.ENCRYPT_MODE, pk);
|
||||
|
||||
si.clientDecCypher = Cipher.getInstance("RSA");
|
||||
si.clientDecCypher.init(Cipher.DECRYPT_MODE, getMsgPair.getPrivate());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (thread != null) {
|
||||
thread.exc("Error exchanging private keys", e);
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return si;
|
||||
} catch (ClientProtocolException e) {
|
||||
throw new IOException(e);
|
||||
|
|
|
@ -17,7 +17,11 @@ import java.util.Map.Entry;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.osm.io.Base64;
|
||||
import net.osmand.plus.osmo.OsMoService.SessionInfo;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
@ -261,6 +265,15 @@ public class OsMoThread {
|
|||
while ((i = readCommand.indexOf('\n')) != -1) {
|
||||
String cmd = readCommand.substring(0, i);
|
||||
readCommand = readCommand.substring(i + 1);
|
||||
if(sessionInfo != null && sessionInfo.clientDecCypher != null) {
|
||||
try {
|
||||
final byte[] inMsg = android.util.Base64.decode(cmd.getBytes(), android.util.Base64.DEFAULT);
|
||||
final byte[] byts = sessionInfo.clientDecCypher.doFinal(inMsg);
|
||||
cmd = new String(byts);
|
||||
} catch (Exception e) {
|
||||
exc("Error decrypting", e);
|
||||
}
|
||||
}
|
||||
queueOfMessages.add(cmd.replace("\\n", "\n"));
|
||||
}
|
||||
}
|
||||
|
@ -457,7 +470,15 @@ public class OsMoThread {
|
|||
res.append(c);
|
||||
}
|
||||
|
||||
return res.toString().trim() + "=\n";
|
||||
String finalCmd = res.toString().trim();
|
||||
if(sessionInfo != null && sessionInfo.clientEncCypher != null) {
|
||||
try {
|
||||
finalCmd = Base64.encode(sessionInfo.clientEncCypher.doFinal(finalCmd.getBytes()));
|
||||
} catch (Exception e) {
|
||||
exc("Error encrypting", e);
|
||||
}
|
||||
}
|
||||
return finalCmd + "=\n";
|
||||
}
|
||||
|
||||
public long getLastCommandTime() {
|
||||
|
|
|
@ -68,6 +68,11 @@ public class SettingsOsMoActivity extends SettingsBaseActivity {
|
|||
showGroupNotifiations.setSummary(R.string.osmo_show_group_notifications_descr);
|
||||
grp.addPreference(showGroupNotifiations);
|
||||
|
||||
CheckBoxPreference useHttps = createCheckBoxPreference(settings.OSMO_USE_HTTPS);
|
||||
useHttps.setTitle(R.string.osmo_use_https);
|
||||
useHttps.setSummary(R.string.osmo_use_https_descr);
|
||||
grp.addPreference(useHttps);
|
||||
|
||||
if (OsmandPlugin.isDevelopment()) {
|
||||
debugPref = new Preference(this);
|
||||
debugPref.setTitle(R.string.osmo_settings_debug);
|
||||
|
|
Loading…
Reference in a new issue