diff --git a/OsmAnd-java/build.gradle b/OsmAnd-java/build.gradle index 4385f9d0b0..0d0a3c265d 100644 --- a/OsmAnd-java/build.gradle +++ b/OsmAnd-java/build.gradle @@ -1,6 +1,6 @@ apply plugin: 'java' apply plugin: 'maven-publish' - + configurations { android } @@ -104,6 +104,9 @@ dependencies { implementation 'com.moparisthebest:junidecode:0.1.1' implementation 'com.vividsolutions:jts-core:1.14.0' implementation 'com.google.openlocationcode:openlocationcode:1.0.4' + implementation('com.github.scribejava:scribejava-apis:7.1.1'){ + exclude group: "com.fasterxml.jackson.core" + } // turn off for now //implementation 'com.atilika.kuromoji:kuromoji-ipadic:0.9.0' implementation 'net.sf.kxml:kxml2:2.1.8' diff --git a/OsmAnd-java/src/main/java/net/osmand/osm/io/NetworkUtils.java b/OsmAnd-java/src/main/java/net/osmand/osm/io/NetworkUtils.java index 282d6addbd..bdf5b6a70e 100644 --- a/OsmAnd-java/src/main/java/net/osmand/osm/io/NetworkUtils.java +++ b/OsmAnd-java/src/main/java/net/osmand/osm/io/NetworkUtils.java @@ -1,27 +1,19 @@ package net.osmand.osm.io; -import java.io.BufferedInputStream; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.InetSocketAddress; -import java.net.MalformedURLException; -import java.net.Proxy; -import java.net.URL; -import java.net.URLEncoder; -import java.util.Map; -import java.util.zip.GZIPOutputStream; - +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; import net.osmand.PlatformUtil; +import net.osmand.osm.oauth.OsmOAuthAuthorizationClient; import net.osmand.util.Algorithms; - import org.apache.commons.logging.Log; +import java.io.*; +import java.net.*; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.zip.GZIPOutputStream; + public class NetworkUtils { private static final Log log = PlatformUtil.getLog(NetworkUtils.class); @@ -55,7 +47,6 @@ public class NetworkUtils { responseBody.append("\n"); //$NON-NLS-1$ } responseBody.append(s); - } is.close(); } @@ -65,9 +56,10 @@ public class NetworkUtils { return e.getMessage(); } } - private static final String BOUNDARY = "CowMooCowMooCowCowCow"; //$NON-NLS-1$ - public static String uploadFile(String urlText, File fileToUpload, String userNamePassword, String formName, boolean gzip, Map additionalMapData){ + public static String uploadFile(String urlText, File fileToUpload, String userNamePassword, + OsmOAuthAuthorizationClient client, + String formName, boolean gzip, Map additionalMapData){ URL url; try { boolean firstPrm =!urlText.contains("?"); @@ -77,47 +69,38 @@ public class NetworkUtils { } log.info("Start uploading file to " + urlText + " " +fileToUpload.getName()); url = new URL(urlText); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setDoInput(true); - conn.setDoOutput(true); - conn.setRequestMethod("POST"); - if(userNamePassword != null) { - conn.setRequestProperty("Authorization", "Basic " + Base64.encode(userNamePassword)); //$NON-NLS-1$ //$NON-NLS-2$ + HttpURLConnection conn; + if (client != null && client.isValidToken()){ + OAuthRequest req = new OAuthRequest(Verb.POST, urlText); + req.setPayload(prepareStream(formName,fileToUpload,gzip)); + client.getService().signRequest(client.getAccessToken(), req); + req.addHeader("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); + try { + Response r = client.getService().execute(req); + if(r.getCode() != 200){ + return r.getBody(); + } + return null; + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } + return null; + } + else { + conn = (HttpURLConnection) url.openConnection(); + conn.setDoInput(true); + conn.setDoOutput(true); + conn.setRequestMethod("POST"); + if(userNamePassword != null) { + conn.setRequestProperty("Authorization", "Basic " + Base64.encode(userNamePassword)); //$NON-NLS-1$ //$NON-NLS-2$ + } } - conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); //$NON-NLS-1$ //$NON-NLS-2$ conn.setRequestProperty("User-Agent", "OsmAnd"); //$NON-NLS-1$ //$NON-NLS-2$ - OutputStream ous = conn.getOutputStream(); -// for (String key : additionalMapData.keySet()) { -// ous.write(("--" + BOUNDARY + "\r\n").getBytes()); -// ous.write(("content-disposition: form-data; name=\"" + key + "\"\r\n").getBytes()); //$NON-NLS-1$ //$NON-NLS-2$ -// ous.write((additionalMapData.get(key) + "\r\n").getBytes()); -// } - ous.write(("--" + BOUNDARY+"\r\n").getBytes()); - String filename = fileToUpload.getName(); - if(gzip){ - filename+=".gz"; - } - ous.write(("content-disposition: form-data; name=\""+formName+"\"; filename=\"" + filename + "\"\r\n").getBytes()); //$NON-NLS-1$ //$NON-NLS-2$ - ous.write(("Content-Type: application/octet-stream\r\n\r\n").getBytes()); //$NON-NLS-1$ - InputStream fis = new FileInputStream(fileToUpload); - BufferedInputStream bis = new BufferedInputStream(fis, 20 * 1024); - ous.flush(); - if(gzip){ - GZIPOutputStream gous = new GZIPOutputStream(ous, 1024); - Algorithms.streamCopy(bis, gous); - gous.flush(); - gous.finish(); - } else { - Algorithms.streamCopy(bis, ous); - } - - ous.write(("\r\n--" + BOUNDARY + "--\r\n").getBytes()); //$NON-NLS-1$ //$NON-NLS-2$ - ous.flush(); - Algorithms.closeStream(bis); - Algorithms.closeStream(ous); - + ous.write(prepareStream(formName,fileToUpload,gzip)); log.info("Finish uploading file " + fileToUpload.getName()); log.info("Response code and message : " + conn.getResponseCode() + " " + conn.getResponseMessage()); if(conn.getResponseCode() != 200){ @@ -136,7 +119,6 @@ public class NetworkUtils { responseBody.append("\n"); //$NON-NLS-1$ } responseBody.append(s); - } is.close(); } @@ -149,6 +131,46 @@ public class NetworkUtils { } } + private static byte[] prepareStream(String formName, File fileToUpload, boolean gzip) { + try { + ByteArrayOutputStream ous = new ByteArrayOutputStream(); +// for (String key : additionalMapData.keySet()) { +// ous.write(("--" + BOUNDARY + "\r\n").getBytes()); +// ous.write(("content-disposition: form-data; name=\"" + key + "\"\r\n").getBytes()); //$NON-NLS-1$ //$NON-NLS-2$ +// ous.write((additionalMapData.get(key) + "\r\n").getBytes()); +// } + ous.write(("--" + BOUNDARY + "\r\n").getBytes()); + + String filename = fileToUpload.getName(); + if (gzip) { + filename += ".gz"; + } + ous.write(("content-disposition: form-data; name=\"" + formName + "\"; filename=\"" + filename + "\"\r\n").getBytes()); //$NON-NLS-1$ //$NON-NLS-2$ + ous.write(("Content-Type: application/octet-stream\r\n\r\n").getBytes()); //$NON-NLS-1$ + InputStream fis = new FileInputStream(fileToUpload); + BufferedInputStream bis = new BufferedInputStream(fis, 20 * 1024); + ous.flush(); + if (gzip) { + GZIPOutputStream gous = new GZIPOutputStream(ous, 1024); + Algorithms.streamCopy(bis, gous); + gous.flush(); + gous.finish(); + gous.close(); + } else { + Algorithms.streamCopy(bis, ous); + } + + ous.write(("\r\n--" + BOUNDARY + "--\r\n").getBytes()); //$NON-NLS-1$ //$NON-NLS-2$ + ous.flush(); + Algorithms.closeStream(bis); + Algorithms.closeStream(ous); + return ous.toByteArray(); + } catch (IOException e) { + e.printStackTrace(); + } + return new byte[0]; + } + public static void setProxy(String host, int port) { if(host != null && port > 0) { InetSocketAddress isa = new InetSocketAddress(host, port); @@ -157,7 +179,7 @@ public class NetworkUtils { proxy = null; } } - + public static Proxy getProxy() { return proxy; } diff --git a/OsmAnd-java/src/main/java/net/osmand/osm/oauth/OsmOAuthAuthorizationClient.java b/OsmAnd-java/src/main/java/net/osmand/osm/oauth/OsmOAuthAuthorizationClient.java new file mode 100644 index 0000000000..bef043e1ce --- /dev/null +++ b/OsmAnd-java/src/main/java/net/osmand/osm/oauth/OsmOAuthAuthorizationClient.java @@ -0,0 +1,134 @@ +// License: GPL. For details, see LICENSE file. +package net.osmand.osm.oauth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.builder.api.DefaultApi10a; +import com.github.scribejava.core.builder.api.OAuth1SignatureType; +import com.github.scribejava.core.model.*; +import com.github.scribejava.core.oauth.OAuth10aService; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +/** + * An OAuth 1.0 authorization client. + * + * @since 2746 + */ +public class OsmOAuthAuthorizationClient { + OAuth10aService service; + OAuth1RequestToken requestToken; + OAuth1AccessToken accessToken; + + public OsmOAuthAuthorizationClient(String key, String secret){ + service = new ServiceBuilder(key) + .apiSecret(secret) + .callback("osmand-oauth://example.com/oauth") + .build(new OsmApi()); + } + + static class OsmApi extends DefaultApi10a { + @Override + public OAuth1SignatureType getSignatureType() { + return OAuth1SignatureType.QUERY_STRING; + } + + @Override + public String getRequestTokenEndpoint() { + return "https://www.openstreetmap.org/oauth/request_token"; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://www.openstreetmap.org/oauth/access_token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://www.openstreetmap.org/oauth/authorize"; + } + } + + public OAuth10aService getService() { + return service; + } + + public void setAccessToken(OAuth1AccessToken accessToken) { this.accessToken = accessToken; } + + public OAuth1AccessToken getAccessToken() { return this.accessToken; } + + public Response performRequestWithoutAuth(String url, String requestMethod, String requestBody) + throws InterruptedException, ExecutionException, IOException { + Verb verb = parseRequestMethod(requestMethod); + OAuthRequest req = new OAuthRequest(verb, url); + req.setPayload(requestBody); + return service.execute(req); + } + + public void performGetRequest(String url, OAuthAsyncRequestCallback callback) { + if (accessToken == null) { + throw new IllegalStateException("Access token is null"); + } + OAuthRequest req = new OAuthRequest(Verb.GET, url); + service.signRequest(accessToken, req); + service.execute(req, callback); + } + + public Response performRequest(String url, String method, String body) + throws InterruptedException, ExecutionException, IOException { + service.getApi().getSignatureType(); + if (accessToken == null) { + throw new IllegalStateException("Access token is null"); + } + Verb verbMethod = parseRequestMethod(method); + OAuthRequest req = new OAuthRequest(verbMethod, url); + req.setPayload(body); + service.signRequest(accessToken, req); + req.addHeader("Content-Type", "application/xml"); + return service.execute(req); + } + + private Verb parseRequestMethod(String method) { + Verb m = Verb.GET; + if (method.equals("POST")) { + m = Verb.POST; + } + if (method.equals("PUT")) { + m = Verb.PUT; + } + if (method.equals("DELETE")) { + m = Verb.DELETE; + } + return m; + } + + public OAuth1RequestToken startOAuth() { + try { + requestToken = service.getRequestToken(); + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } + return requestToken; + } + + public OAuth1AccessToken authorize(String oauthVerifier) { + try { + setAccessToken(service.getAccessToken(requestToken, oauthVerifier)); + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } + return accessToken; + } + + public boolean isValidToken() { + return !(accessToken == null); + } +} diff --git a/OsmAnd/build.gradle b/OsmAnd/build.gradle index 58803bac25..e18cb21e76 100644 --- a/OsmAnd/build.gradle +++ b/OsmAnd/build.gradle @@ -567,10 +567,10 @@ dependencies { implementation ("com.github.HITGIF:TextFieldBoxes:1.4.5"){ exclude group: 'com.android.support' } - implementation 'com.jaredrummler:colorpicker:1.1.0' implementation('com.github.scribejava:scribejava-apis:7.1.1'){ exclude group: "com.fasterxml.jackson.core" } + implementation 'com.jaredrummler:colorpicker:1.1.0' huaweiImplementation files('libs/huawei-android-drm_v2.5.2.300.jar') freehuaweiImplementation files('libs/huawei-android-drm_v2.5.2.300.jar') diff --git a/OsmAnd/src/net/osmand/plus/download/DownloadIndexesThread.java b/OsmAnd/src/net/osmand/plus/download/DownloadIndexesThread.java index 4b0dd632aa..8f826e76b1 100644 --- a/OsmAnd/src/net/osmand/plus/download/DownloadIndexesThread.java +++ b/OsmAnd/src/net/osmand/plus/download/DownloadIndexesThread.java @@ -5,6 +5,7 @@ import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.DialogInterface; import android.content.Intent; +import android.net.TrafficStats; import android.net.Uri; import android.os.AsyncTask; import android.os.AsyncTask.Status; @@ -336,6 +337,8 @@ public class DownloadIndexesThread { @Override protected DownloadResources doInBackground(Void... params) { + final int THREAD_ID = 10103; + TrafficStats.setThreadStatsTag(THREAD_ID); DownloadResources result = null; DownloadOsmandIndexesHelper.IndexFileList indexFileList = DownloadOsmandIndexesHelper.getIndexesList(ctx); if (indexFileList != null) { diff --git a/OsmAnd/src/net/osmand/plus/osmedit/EditPOIMenuController.java b/OsmAnd/src/net/osmand/plus/osmedit/EditPOIMenuController.java index b94ac7cc1c..7d04c73252 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/EditPOIMenuController.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/EditPOIMenuController.java @@ -2,10 +2,8 @@ package net.osmand.plus.osmedit; import android.content.DialogInterface; import android.graphics.drawable.Drawable; - import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; - import net.osmand.data.PointDescription; import net.osmand.osm.PoiType; import net.osmand.plus.OsmandPlugin; @@ -14,7 +12,7 @@ import net.osmand.plus.activities.MapActivity; import net.osmand.plus.mapcontextmenu.MenuController; import net.osmand.plus.osmedit.OsmPoint.Action; import net.osmand.plus.osmedit.dialogs.SendPoiDialogFragment; -import net.osmand.plus.osmedit.oauth.OsmOAuthAuthorizationClient; +import net.osmand.plus.osmedit.oauth.OsmOAuthAuthorizationAdapter; import net.osmand.plus.render.RenderingIcons; import net.osmand.util.Algorithms; @@ -40,7 +38,7 @@ public class EditPOIMenuController extends MenuController { public void buttonPressed() { MapActivity activity = getMapActivity(); if (plugin != null && activity != null) { - OsmOAuthAuthorizationClient client = new OsmOAuthAuthorizationClient(activity.getMyApplication()); + OsmOAuthAuthorizationAdapter client = new OsmOAuthAuthorizationAdapter(activity.getMyApplication()); if (client.isValidToken()){ new SendPoiDialogFragment.SimpleProgressDialogPoiUploader(activity). showProgressDialog(new OsmPoint[] { getOsmPoint() }, false, false); diff --git a/OsmAnd/src/net/osmand/plus/osmedit/OpenstreetmapRemoteUtil.java b/OsmAnd/src/net/osmand/plus/osmedit/OpenstreetmapRemoteUtil.java index c8bf73e423..e550d25d73 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/OpenstreetmapRemoteUtil.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/OpenstreetmapRemoteUtil.java @@ -2,7 +2,8 @@ package net.osmand.plus.osmedit; import android.util.Xml; import android.widget.Toast; - +import com.github.scribejava.core.model.Response; +import gnu.trove.list.array.TLongArrayList; import net.osmand.NativeLibrary; import net.osmand.PlatformUtil; import net.osmand.data.Amenity; @@ -17,39 +18,29 @@ import net.osmand.osm.edit.Entity.EntityType; import net.osmand.osm.edit.EntityInfo; import net.osmand.osm.edit.Node; import net.osmand.osm.edit.Way; -import net.osmand.osm.io.Base64; import net.osmand.osm.io.NetworkUtils; import net.osmand.osm.io.OsmBaseStorage; import net.osmand.plus.OsmandApplication; -import net.osmand.plus.osmedit.oauth.OsmOAuthAuthorizationClient; -import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.Version; +import net.osmand.plus.osmedit.oauth.OsmOAuthAuthorizationAdapter; +import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.util.MapUtils; - import org.apache.commons.logging.Log; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; -import java.io.BufferedReader; -import java.io.BufferedWriter; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; import java.io.StringWriter; -import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.text.MessageFormat; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; - -import gnu.trove.list.array.TLongArrayList; +import java.util.concurrent.ExecutionException; public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil { @@ -100,12 +91,16 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil { private final static String URL_TO_UPLOAD_GPX = getSiteApi() + "api/0.6/gpx/create"; public String uploadGPXFile(String tagstring, String description, String visibility, File f) { + OsmOAuthAuthorizationAdapter adapter = new OsmOAuthAuthorizationAdapter(ctx); String url = URL_TO_UPLOAD_GPX; Map additionalData = new LinkedHashMap(); additionalData.put("description", description); additionalData.put("tags", tagstring); additionalData.put("visibility", visibility); - return NetworkUtils.uploadFile(url, f, settings.USER_NAME.get() + ":" + settings.USER_PASSWORD.get(), "file", + return NetworkUtils.uploadFile(url, f, + settings.USER_NAME.get() + ":" + settings.USER_PASSWORD.get(), + adapter.getClient(), + "file", true, additionalData); } @@ -113,59 +108,14 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil { boolean doAuthenticate) { log.info("Sending request " + url); //$NON-NLS-1$ try { - HttpURLConnection connection = NetworkUtils.getHttpURLConnection(url); - - connection.setConnectTimeout(15000); - connection.setRequestMethod(requestMethod); - connection.setRequestProperty("User-Agent", Version.getFullVersion(ctx)); //$NON-NLS-1$ - StringBuilder responseBody = new StringBuilder(); - if (doAuthenticate) { - OsmOAuthAuthorizationClient client = new OsmOAuthAuthorizationClient(ctx); - if (client.isValidToken()){ - connection.addRequestProperty("Authorization", "OAuth " + client.getAccessToken()); - } - else { - String token = settings.USER_NAME.get() + ":" + settings.USER_PASSWORD.get(); //$NON-NLS-1$ - connection.addRequestProperty("Authorization", "Basic " + Base64.encode(token.getBytes("UTF-8"))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - } + if (doAuthenticate){ + OsmOAuthAuthorizationAdapter client = new OsmOAuthAuthorizationAdapter(ctx); + Response response = client.performRequest(url,requestMethod,requestBody); + return response.getBody(); } - connection.setDoInput(true); - if (requestMethod.equals("PUT") || requestMethod.equals("POST") || requestMethod.equals("DELETE")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - connection.setDoOutput(true); - connection.setRequestProperty("Content-type", "text/xml"); //$NON-NLS-1$ //$NON-NLS-2$ - OutputStream out = connection.getOutputStream(); - if (requestBody != null) { - BufferedWriter bwr = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"), 1024); //$NON-NLS-1$ - bwr.write(requestBody); - bwr.flush(); - } - out.close(); - } - connection.connect(); - if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) { - String msg = userOperation - + " " + ctx.getString(R.string.failed_op) + " : " + connection.getResponseMessage(); //$NON-NLS-1$//$NON-NLS-2$ - log.error(msg); - showWarning(msg); - } else { - log.info("Response : " + connection.getResponseMessage()); //$NON-NLS-1$ - // populate return fields. - responseBody.setLength(0); - InputStream i = connection.getInputStream(); - if (i != null) { - BufferedReader in = new BufferedReader(new InputStreamReader(i, "UTF-8"), 256); //$NON-NLS-1$ - String s; - boolean f = true; - while ((s = in.readLine()) != null) { - if (!f) { - responseBody.append("\n"); //$NON-NLS-1$ - } else { - f = false; - } - responseBody.append(s); - } - } - return responseBody.toString(); + else { + OsmOAuthAuthorizationAdapter client = new OsmOAuthAuthorizationAdapter(ctx); + client.performRequestWithoutAuth(url,requestMethod,requestBody); } } catch (NullPointerException e) { // that's tricky case why NPE is thrown to fix that problem httpClient could be used @@ -180,6 +130,14 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil { log.error(userOperation + " " + ctx.getString(R.string.failed_op), e); //$NON-NLS-1$ showWarning(MessageFormat.format(ctx.getResources().getString(R.string.shared_string_action_template) + ": " + ctx.getResources().getString(R.string.shared_string_io_error), userOperation)); + } catch (InterruptedException e) { + log.error(userOperation + " " + ctx.getString(R.string.failed_op), e); //$NON-NLS-1$ + showWarning(MessageFormat.format(ctx.getResources().getString(R.string.shared_string_action_template) + + ": " + ctx.getResources().getString(R.string.shared_string_unexpected_error), userOperation)); + } catch (ExecutionException e) { + log.error(userOperation + " " + ctx.getString(R.string.failed_op), e); //$NON-NLS-1$ + showWarning(MessageFormat.format(ctx.getResources().getString(R.string.shared_string_action_template) + + ": " + ctx.getResources().getString(R.string.shared_string_unexpected_error), userOperation)); } return null; @@ -213,12 +171,16 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil { } catch (IOException e) { log.error("Unhandled exception", e); //$NON-NLS-1$ } - String response = sendRequest( - getSiteApi() + "api/0.6/changeset/create/", "PUT", writer.getBuffer().toString(), ctx.getString(R.string.opening_changeset), true); //$NON-NLS-1$ //$NON-NLS-2$ - if (response != null && response.length() > 0) { - id = Long.parseLong(response); - } - + String response = sendRequest( + getSiteApi() + "api/0.6/changeset/create/", "PUT", writer.getBuffer().toString(), ctx.getString(R.string.opening_changeset), true); //$NON-NLS-1$ //$NON-NLS-2$ + try { + if (response != null && response.length() > 0) { + log.debug(response); + id = Long.parseLong(response); + } + } catch (Exception e) { + e.printStackTrace(); + } return id; } diff --git a/OsmAnd/src/net/osmand/plus/osmedit/OsmBugsRemoteUtil.java b/OsmAnd/src/net/osmand/plus/osmedit/OsmBugsRemoteUtil.java index 581206fb98..75b226eb3f 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/OsmBugsRemoteUtil.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/OsmBugsRemoteUtil.java @@ -5,13 +5,12 @@ import net.osmand.PlatformUtil; import net.osmand.osm.io.Base64; import net.osmand.osm.io.NetworkUtils; import net.osmand.plus.OsmandApplication; -import net.osmand.plus.osmedit.oauth.OsmOAuthAuthorizationClient; -import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.Version; import net.osmand.plus.osmedit.OsmPoint.Action; +import net.osmand.plus.osmedit.oauth.OsmOAuthAuthorizationAdapter; +import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.util.Algorithms; - import org.apache.commons.logging.Log; import java.io.FileNotFoundException; @@ -110,7 +109,7 @@ public class OsmBugsRemoteUtil implements OsmBugsUtil { private OsmBugResult editingPOI(String url, String requestMethod, String userOperation, boolean anonymous) { - OsmOAuthAuthorizationClient client = new OsmOAuthAuthorizationClient(this.app); + OsmOAuthAuthorizationAdapter client = new OsmOAuthAuthorizationAdapter(this.app); OsmBugResult r = new OsmBugResult(); try { HttpURLConnection connection = NetworkUtils.getHttpURLConnection(url); @@ -121,7 +120,7 @@ public class OsmBugsRemoteUtil implements OsmBugsUtil { if (!anonymous) { if (client.isValidToken()){ - connection.addRequestProperty("Authorization", "OAuth " + client.getAccessToken()); + connection.addRequestProperty("Authorization", "OAuth " + client.getClient().getAccessToken().getToken()); } else { String token = settings.USER_NAME.get() + ":" + settings.USER_PASSWORD.get(); //$NON-NLS-1$ diff --git a/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingPlugin.java b/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingPlugin.java index 427831de54..f1b33b8f79 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingPlugin.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingPlugin.java @@ -13,11 +13,9 @@ import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.Spinner; import android.widget.Toast; - import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; - import net.osmand.AndroidUtils; import net.osmand.PlatformUtil; import net.osmand.data.Amenity; @@ -25,13 +23,8 @@ import net.osmand.data.MapObject; import net.osmand.data.TransportStop; import net.osmand.osm.PoiType; import net.osmand.osm.edit.Entity; -import net.osmand.plus.ContextMenuAdapter; +import net.osmand.plus.*; import net.osmand.plus.ContextMenuAdapter.ItemClickListener; -import net.osmand.plus.ContextMenuItem; -import net.osmand.plus.OsmandApplication; -import net.osmand.plus.OsmandPlugin; -import net.osmand.plus.settings.backend.OsmandSettings; -import net.osmand.plus.R; import net.osmand.plus.activities.EnumAdapter; import net.osmand.plus.activities.EnumAdapter.IEnumWithResource; import net.osmand.plus.activities.MapActivity; @@ -43,22 +36,16 @@ import net.osmand.plus.myplaces.AvailableGPXFragment.GpxInfo; import net.osmand.plus.myplaces.FavoritesActivity; import net.osmand.plus.osmedit.OsmPoint.Action; import net.osmand.plus.quickaction.QuickActionType; +import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.settings.fragments.BaseSettingsFragment; import net.osmand.plus.views.OsmandMapTileView; import net.osmand.util.Algorithms; - import org.apache.commons.logging.Log; import java.util.ArrayList; import java.util.List; -import static net.osmand.aidlapi.OsmAndCustomizationConstants.MAP_CONTEXT_MENU_CREATE_POI; -import static net.osmand.aidlapi.OsmAndCustomizationConstants.MAP_CONTEXT_MENU_MODIFY_OSM_CHANGE; -import static net.osmand.aidlapi.OsmAndCustomizationConstants.MAP_CONTEXT_MENU_MODIFY_OSM_NOTE; -import static net.osmand.aidlapi.OsmAndCustomizationConstants.MAP_CONTEXT_MENU_MODIFY_POI; -import static net.osmand.aidlapi.OsmAndCustomizationConstants.MAP_CONTEXT_MENU_OPEN_OSM_NOTE; -import static net.osmand.aidlapi.OsmAndCustomizationConstants.OSM_EDITS; -import static net.osmand.aidlapi.OsmAndCustomizationConstants.OSM_NOTES; +import static net.osmand.aidlapi.OsmAndCustomizationConstants.*; import static net.osmand.plus.ContextMenuAdapter.makeDeleteAction; @@ -464,7 +451,8 @@ public class OsmEditingPlugin extends OsmandPlugin { public boolean sendGPXFiles(final Activity la, AvailableGPXFragment f, final GpxInfo... info) { String name = settings.USER_NAME.get(); String pwd = settings.USER_PASSWORD.get(); - if (Algorithms.isEmpty(name) || Algorithms.isEmpty(pwd)) { + String authToken = settings.USER_ACCESS_TOKEN.get(); + if ((Algorithms.isEmpty(name) || Algorithms.isEmpty(pwd)) && Algorithms.isEmpty(authToken)) { Toast.makeText(la, R.string.validate_gpx_upload_name_pwd, Toast.LENGTH_LONG).show(); return false; } diff --git a/OsmAnd/src/net/osmand/plus/osmedit/SettingsOsmEditingActivity.java b/OsmAnd/src/net/osmand/plus/osmedit/SettingsOsmEditingActivity.java index c0262e436f..651fc7ff07 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/SettingsOsmEditingActivity.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/SettingsOsmEditingActivity.java @@ -17,20 +17,19 @@ import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import android.widget.Toast; - import com.github.scribejava.core.model.OAuthAsyncRequestCallback; import com.github.scribejava.core.model.Response; -import net.osmand.plus.OsmandPlugin; -import net.osmand.plus.osmedit.oauth.OsmOAuthAuthorizationClient; import net.osmand.plus.OsmandApplication; +import net.osmand.plus.OsmandPlugin; import net.osmand.plus.R; import net.osmand.plus.activities.SettingsBaseActivity; +import net.osmand.plus.osmedit.oauth.OsmOAuthAuthorizationAdapter; import net.osmand.plus.settings.backend.OsmAndAppCustomization; import java.io.IOException; public class SettingsOsmEditingActivity extends SettingsBaseActivity { - OsmOAuthAuthorizationClient client; + OsmOAuthAuthorizationAdapter client; @Override public void onCreate(Bundle savedInstanceState) { @@ -44,7 +43,7 @@ public class SettingsOsmEditingActivity extends SettingsBaseActivity { ((OsmandApplication) getApplication()).applyTheme(this); super.onCreate(savedInstanceState); - client = new OsmOAuthAuthorizationClient(this.getMyApplication()); + client = new OsmOAuthAuthorizationAdapter(this.getMyApplication()); getToolbar().setTitle(R.string.osm_settings); @SuppressWarnings("deprecation") diff --git a/OsmAnd/src/net/osmand/plus/osmedit/oauth/OsmOAuthAuthorizationAdapter.java b/OsmAnd/src/net/osmand/plus/osmedit/oauth/OsmOAuthAuthorizationAdapter.java new file mode 100644 index 0000000000..5d2313c078 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/osmedit/oauth/OsmOAuthAuthorizationAdapter.java @@ -0,0 +1,79 @@ +package net.osmand.plus.osmedit.oauth; + +import android.net.TrafficStats; +import android.view.View; +import android.view.ViewGroup; +import android.webkit.WebView; +import com.github.scribejava.core.model.OAuth1AccessToken; +import com.github.scribejava.core.model.OAuth1RequestToken; +import com.github.scribejava.core.model.OAuthAsyncRequestCallback; +import com.github.scribejava.core.model.Response; +import net.osmand.osm.oauth.OsmOAuthAuthorizationClient; +import net.osmand.plus.BuildConfig; +import net.osmand.plus.OsmandApplication; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class OsmOAuthAuthorizationAdapter { + OsmandApplication application; + OsmOAuthAuthorizationClient client = new OsmOAuthAuthorizationClient(BuildConfig.CONSUMER_KEY, BuildConfig.CONSUMER_SECRET); + + public OsmOAuthAuthorizationAdapter(OsmandApplication application) { + final int THREAD_ID = 10101; + TrafficStats.setThreadStatsTag(THREAD_ID); + this.application = application; + restoreToken(); + } + + public OsmOAuthAuthorizationClient getClient() { + return client; + } + + public boolean isValidToken() { + return client.isValidToken(); + } + + public void restoreToken() { + String token = application.getSettings().USER_ACCESS_TOKEN.get(); + String tokenSecret = application.getSettings().USER_ACCESS_TOKEN_SECRET.get(); + client.setAccessToken(new OAuth1AccessToken(token, tokenSecret)); + } + + public void startOAuth(ViewGroup rootLayout) { + OAuth1RequestToken requestToken = client.startOAuth(); + loadWebView(rootLayout, client.getService().getAuthorizationUrl(requestToken)); + } + + private void saveToken() { + OAuth1AccessToken accessToken = client.getAccessToken(); + application.getSettings().USER_ACCESS_TOKEN.set(accessToken.getToken()); + application.getSettings().USER_ACCESS_TOKEN_SECRET.set(accessToken.getTokenSecret()); + } + + private void loadWebView(ViewGroup root, String url) { + WebView webView = new WebView(root.getContext()); + webView.requestFocus(View.FOCUS_DOWN); + webView.loadUrl(url); + root.addView(webView); + } + + public void performGetRequest(String url, OAuthAsyncRequestCallback callback) { + client.performGetRequest(url, callback); + } + + public Response performRequest(String url, String method, String body) + throws InterruptedException, ExecutionException, IOException { + return client.performRequest(url, method, body); + } + + public Response performRequestWithoutAuth(String url, String method, String body) + throws InterruptedException, ExecutionException, IOException { + return client.performRequestWithoutAuth(url, method, body); + } + + public void authorize(String oauthVerifier) { + client.authorize(oauthVerifier); + saveToken(); + } +} diff --git a/OsmAnd/src/net/osmand/plus/osmedit/oauth/OsmOAuthAuthorizationClient.java b/OsmAnd/src/net/osmand/plus/osmedit/oauth/OsmOAuthAuthorizationClient.java deleted file mode 100644 index 1e53c48628..0000000000 --- a/OsmAnd/src/net/osmand/plus/osmedit/oauth/OsmOAuthAuthorizationClient.java +++ /dev/null @@ -1,119 +0,0 @@ -// License: GPL. For details, see LICENSE file. -package net.osmand.plus.osmedit.oauth; - - -import android.net.TrafficStats; -import android.view.View; -import android.view.ViewGroup; -import android.webkit.WebView; -import com.github.scribejava.core.builder.ServiceBuilder; -import com.github.scribejava.core.builder.api.DefaultApi10a; -import com.github.scribejava.core.model.*; -import com.github.scribejava.core.oauth.OAuth10aService; -import net.osmand.plus.BuildConfig; -import net.osmand.plus.OsmandApplication; - -import java.io.IOException; -import java.util.concurrent.ExecutionException; - -/** - * An OAuth 1.0 authorization client. - * - * @since 2746 - */ -public class OsmOAuthAuthorizationClient { - - OAuth10aService service = new ServiceBuilder(BuildConfig.CONSUMER_KEY) - .apiSecret(BuildConfig.CONSUMER_SECRET) - .debug() - .callback("osmand-oauth://example.com/oauth") - .build(new OsmApi()); - - OAuth1RequestToken requestToken; - OAuth1AccessToken accessToken; - OsmandApplication application; - - static class OsmApi extends DefaultApi10a { - - @Override - public String getRequestTokenEndpoint() { return "https://www.openstreetmap.org/oauth/request_token"; } - - @Override - public String getAccessTokenEndpoint() { - return "https://www.openstreetmap.org/oauth/access_token"; - } - - @Override - protected String getAuthorizationBaseUrl() { - return "https://www.openstreetmap.org/oauth/authorize"; - } - } - - public OsmOAuthAuthorizationClient(OsmandApplication application) { - final int THREAD_ID = 10101; - TrafficStats.setThreadStatsTag(THREAD_ID); - this.application = application; - restoreToken(); - } - - public String getAccessToken() { - return this.accessToken.getToken(); - } - - public void performGetRequest(String url,OAuthAsyncRequestCallback callback) { - if (accessToken == null) { - throw new IllegalStateException("Access token is null"); - } - OAuthRequest req = new OAuthRequest(Verb.GET, url); - service.signRequest(accessToken, req); - service.execute(req, callback); - } - - public void startOAuth(ViewGroup rootLayout) { - try { - requestToken = service.getRequestToken(); - loadWebView(rootLayout, service.getAuthorizationUrl(requestToken)); - } catch (IOException e) { - e.printStackTrace(); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (ExecutionException e) { - e.printStackTrace(); - } - } - - public void authorize(String oauthVerifier) { - try { - accessToken = service.getAccessToken(requestToken, oauthVerifier); - } catch (IOException e) { - e.printStackTrace(); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (ExecutionException e) { - e.printStackTrace(); - } - saveToken(); - } - - public boolean isValidToken(){ - return !(accessToken == null); - } - - public void restoreToken() { - String token = application.getSettings().USER_ACCESS_TOKEN.get(); - String tokenSecret = application.getSettings().USER_ACCESS_TOKEN_SECRET.get(); - accessToken = new OAuth1AccessToken(token, tokenSecret); - } - - private void saveToken() { - application.getSettings().USER_ACCESS_TOKEN.set(accessToken.getToken()); - application.getSettings().USER_ACCESS_TOKEN_SECRET.set(accessToken.getTokenSecret()); - } - - private void loadWebView(ViewGroup root, String url) { - WebView webView = new WebView(root.getContext()); - webView.requestFocus(View.FOCUS_DOWN); - webView.loadUrl(url); - root.addView(webView); - } -}