Merge pull request #9932 from osmandapp/issue_175_osmedit_use_oauth
Issue 175 osmedit use oauth
This commit is contained in:
commit
3e8f543942
16 changed files with 722 additions and 143 deletions
|
@ -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'
|
||||
|
|
|
@ -1,30 +1,22 @@
|
|||
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);
|
||||
|
||||
private static final String GPX_UPLOAD_USER_AGENT = "OsmGPXUploadAgent";
|
||||
private static Proxy proxy = null;
|
||||
|
||||
public static String sendGetRequest(String urlText, String userNamePassword, StringBuilder responseBody){
|
||||
|
@ -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<String, String> additionalMapData){
|
||||
public static String uploadFile(String urlText, File fileToUpload, String userNamePassword,
|
||||
OsmOAuthAuthorizationClient client,
|
||||
String formName, boolean gzip, Map<String, String> additionalMapData){
|
||||
URL url;
|
||||
try {
|
||||
boolean firstPrm =!urlText.contains("?");
|
||||
|
@ -77,34 +69,48 @@ 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);
|
||||
client.getService().signRequest(client.getAccessToken(), req);
|
||||
req.addHeader("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
|
||||
try {
|
||||
Response r = client.getHttpClient().execute(GPX_UPLOAD_USER_AGENT, req.getHeaders(), req.getVerb(),
|
||||
req.getCompleteUrl(), fileToUpload);
|
||||
if (r.getCode() != 200) {
|
||||
return r.getBody();
|
||||
}
|
||||
return null;
|
||||
} catch (InterruptedException e) {
|
||||
log.error(e);
|
||||
} catch (ExecutionException e) {
|
||||
log.error(e);
|
||||
}
|
||||
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());
|
||||
ous.write(("--" + BOUNDARY + "\r\n").getBytes());
|
||||
String filename = fileToUpload.getName();
|
||||
if(gzip){
|
||||
filename+=".gz";
|
||||
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);
|
||||
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){
|
||||
if (gzip) {
|
||||
GZIPOutputStream gous = new GZIPOutputStream(ous, 1024);
|
||||
Algorithms.streamCopy(bis, gous);
|
||||
gous.flush();
|
||||
|
@ -112,8 +118,7 @@ public class NetworkUtils {
|
|||
} else {
|
||||
Algorithms.streamCopy(bis, ous);
|
||||
}
|
||||
|
||||
ous.write(("\r\n--" + BOUNDARY + "--\r\n").getBytes()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
ous.write(("\r\n--" + BOUNDARY + "--\r\n").getBytes()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
ous.flush();
|
||||
Algorithms.closeStream(bis);
|
||||
Algorithms.closeStream(ous);
|
||||
|
@ -136,7 +141,6 @@ public class NetworkUtils {
|
|||
responseBody.append("\n"); //$NON-NLS-1$
|
||||
}
|
||||
responseBody.append(s);
|
||||
|
||||
}
|
||||
is.close();
|
||||
}
|
||||
|
@ -157,7 +161,6 @@ public class NetworkUtils {
|
|||
proxy = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Proxy getProxy() {
|
||||
return proxy;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,259 @@
|
|||
package net.osmand.osm.oauth;
|
||||
|
||||
import com.github.scribejava.core.exceptions.OAuthException;
|
||||
import com.github.scribejava.core.httpclient.HttpClient;
|
||||
import com.github.scribejava.core.httpclient.jdk.JDKHttpClientConfig;
|
||||
import com.github.scribejava.core.httpclient.jdk.JDKHttpFuture;
|
||||
import com.github.scribejava.core.httpclient.multipart.MultipartPayload;
|
||||
import com.github.scribejava.core.httpclient.multipart.MultipartUtils;
|
||||
import com.github.scribejava.core.model.*;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class OsmAndJDKHttpClient implements HttpClient {
|
||||
private static final String BOUNDARY = "CowMooCowMooCowCowCow";
|
||||
private final JDKHttpClientConfig config;
|
||||
|
||||
public OsmAndJDKHttpClient() {
|
||||
this(JDKHttpClientConfig.defaultConfig());
|
||||
}
|
||||
|
||||
public OsmAndJDKHttpClient(JDKHttpClientConfig clientConfig) {
|
||||
config = clientConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Future<T> executeAsync(String userAgent, Map<String, String> headers, Verb httpVerb, String completeUrl,
|
||||
byte[] bodyContents, OAuthAsyncRequestCallback<T> callback, OAuthRequest.ResponseConverter<T> converter) {
|
||||
|
||||
return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, BodyType.BYTE_ARRAY, bodyContents, callback,
|
||||
converter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Future<T> executeAsync(String userAgent, Map<String, String> headers, Verb httpVerb, String completeUrl,
|
||||
MultipartPayload bodyContents, OAuthAsyncRequestCallback<T> callback,
|
||||
OAuthRequest.ResponseConverter<T> converter) {
|
||||
|
||||
return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, BodyType.MULTIPART, bodyContents, callback,
|
||||
converter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Future<T> executeAsync(String userAgent, Map<String, String> headers, Verb httpVerb, String completeUrl,
|
||||
String bodyContents, OAuthAsyncRequestCallback<T> callback, OAuthRequest.ResponseConverter<T> converter) {
|
||||
|
||||
return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, BodyType.STRING, bodyContents, callback,
|
||||
converter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Future<T> executeAsync(String userAgent, Map<String, String> headers, Verb httpVerb, String completeUrl,
|
||||
File bodyContents, OAuthAsyncRequestCallback<T> callback, OAuthRequest.ResponseConverter<T> converter) {
|
||||
return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, BodyType.STREAM, bodyContents, callback,
|
||||
converter);
|
||||
}
|
||||
|
||||
private <T> Future<T> doExecuteAsync(String userAgent, Map<String, String> headers, Verb httpVerb,
|
||||
String completeUrl, BodyType bodyType, Object bodyContents, OAuthAsyncRequestCallback<T> callback,
|
||||
OAuthRequest.ResponseConverter<T> converter) {
|
||||
try {
|
||||
final Response response = doExecute(userAgent, headers, httpVerb, completeUrl, bodyType, bodyContents);
|
||||
@SuppressWarnings("unchecked") final T t = converter == null ? (T) response : converter.convert(response);
|
||||
if (callback != null) {
|
||||
callback.onCompleted(t);
|
||||
}
|
||||
return new JDKHttpFuture<>(t);
|
||||
} catch (IOException | RuntimeException e) {
|
||||
if (callback != null) {
|
||||
callback.onThrowable(e);
|
||||
}
|
||||
return new JDKHttpFuture<>(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response execute(String userAgent, Map<String, String> headers, Verb httpVerb, String completeUrl,
|
||||
byte[] bodyContents) throws InterruptedException, ExecutionException, IOException {
|
||||
return doExecute(userAgent, headers, httpVerb, completeUrl, BodyType.BYTE_ARRAY, bodyContents);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response execute(String userAgent, Map<String, String> headers, Verb httpVerb, String completeUrl,
|
||||
MultipartPayload multipartPayloads) throws InterruptedException, ExecutionException, IOException {
|
||||
return doExecute(userAgent, headers, httpVerb, completeUrl, BodyType.MULTIPART, multipartPayloads);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response execute(String userAgent, Map<String, String> headers, Verb httpVerb, String completeUrl,
|
||||
String bodyContents) throws InterruptedException, ExecutionException, IOException {
|
||||
return doExecute(userAgent, headers, httpVerb, completeUrl, BodyType.STRING, bodyContents);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response execute(String userAgent, Map<String, String> headers, Verb httpVerb, String completeUrl,
|
||||
File bodyContents) throws InterruptedException, ExecutionException, IOException {
|
||||
return doExecute(userAgent, headers, httpVerb, completeUrl, BodyType.STREAM, bodyContents);
|
||||
}
|
||||
|
||||
private Response doExecute(String userAgent, Map<String, String> headers, Verb httpVerb, String completeUrl,
|
||||
BodyType bodyType, Object bodyContents) throws IOException {
|
||||
final URL url = new URL(completeUrl);
|
||||
final HttpURLConnection connection;
|
||||
if (config.getProxy() == null) {
|
||||
connection = (HttpURLConnection) url.openConnection();
|
||||
} else {
|
||||
connection = (HttpURLConnection) url.openConnection(config.getProxy());
|
||||
}
|
||||
connection.setInstanceFollowRedirects(config.isFollowRedirects());
|
||||
connection.setRequestMethod(httpVerb.name());
|
||||
if (config.getConnectTimeout() != null) {
|
||||
connection.setConnectTimeout(config.getConnectTimeout());
|
||||
}
|
||||
if (config.getReadTimeout() != null) {
|
||||
connection.setReadTimeout(config.getReadTimeout());
|
||||
}
|
||||
addHeaders(connection, headers, userAgent);
|
||||
if (httpVerb.isPermitBody()) {
|
||||
bodyType.setBody(connection, bodyContents, httpVerb.isRequiresBody());
|
||||
}
|
||||
|
||||
try {
|
||||
connection.connect();
|
||||
final int responseCode = connection.getResponseCode();
|
||||
return new Response(responseCode, connection.getResponseMessage(), parseHeaders(connection),
|
||||
responseCode >= 200 && responseCode < 400 ? connection.getInputStream()
|
||||
: connection.getErrorStream());
|
||||
} catch (UnknownHostException e) {
|
||||
throw new OAuthException("The IP address of a host could not be determined.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private enum BodyType {
|
||||
BYTE_ARRAY {
|
||||
@Override
|
||||
void setBody(HttpURLConnection connection, Object bodyContents, boolean requiresBody) throws IOException {
|
||||
addBody(connection, (byte[]) bodyContents, requiresBody);
|
||||
}
|
||||
},
|
||||
STREAM {
|
||||
@Override
|
||||
void setBody(HttpURLConnection connection, Object bodyContents, boolean requiresBody) throws IOException {
|
||||
addBody(connection, (File) bodyContents, requiresBody);
|
||||
}
|
||||
},
|
||||
MULTIPART {
|
||||
@Override
|
||||
void setBody(HttpURLConnection connection, Object bodyContents, boolean requiresBody) throws IOException {
|
||||
addBody(connection, (MultipartPayload) bodyContents, requiresBody);
|
||||
}
|
||||
},
|
||||
STRING {
|
||||
@Override
|
||||
void setBody(HttpURLConnection connection, Object bodyContents, boolean requiresBody) throws IOException {
|
||||
addBody(connection, ((String) bodyContents).getBytes(), requiresBody);
|
||||
}
|
||||
};
|
||||
|
||||
abstract void setBody(HttpURLConnection connection, Object bodyContents, boolean requiresBody)
|
||||
throws IOException;
|
||||
}
|
||||
|
||||
private static Map<String, String> parseHeaders(HttpURLConnection conn) {
|
||||
final Map<String, String> headers = new HashMap<>();
|
||||
|
||||
for (Map.Entry<String, List<String>> headerField : conn.getHeaderFields().entrySet()) {
|
||||
final String key = headerField.getKey();
|
||||
final String value = headerField.getValue().get(0);
|
||||
if ("Content-Encoding".equalsIgnoreCase(key)) {
|
||||
headers.put("Content-Encoding", value);
|
||||
} else {
|
||||
headers.put(key, value);
|
||||
}
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
private static void addHeaders(HttpURLConnection connection, Map<String, String> headers, String userAgent) {
|
||||
for (Map.Entry<String, String> header : headers.entrySet()) {
|
||||
connection.setRequestProperty(header.getKey(), header.getValue());
|
||||
}
|
||||
|
||||
if (userAgent != null) {
|
||||
connection.setRequestProperty(OAuthConstants.USER_AGENT_HEADER_NAME, userAgent);
|
||||
}
|
||||
}
|
||||
|
||||
private static void addBody(HttpURLConnection connection, File file, boolean requiresBody) throws IOException {
|
||||
if (requiresBody) {
|
||||
String filename = file.getName();
|
||||
String formName = "file";
|
||||
InputStream stream = new FileInputStream(file);
|
||||
connection.setDoInput(true);
|
||||
connection.setDoOutput(true);
|
||||
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
connection.setRequestProperty("User-Agent", "OsmAnd"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
final OutputStream ous = connection.getOutputStream();
|
||||
ous.write(("--" + BOUNDARY + "\r\n").getBytes());
|
||||
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$
|
||||
BufferedInputStream bis = new BufferedInputStream(stream, 20 * 1024);
|
||||
ous.flush();
|
||||
Algorithms.streamCopy(bis, ous);
|
||||
ous.write(("\r\n--" + BOUNDARY + "--\r\n").getBytes()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
ous.flush();
|
||||
Algorithms.closeStream(bis);
|
||||
}
|
||||
}
|
||||
|
||||
private static void addBody(HttpURLConnection connection, byte[] content, boolean requiresBody) throws IOException {
|
||||
final int contentLength = content.length;
|
||||
if (requiresBody || contentLength > 0) {
|
||||
connection.setDoOutput(true);
|
||||
final OutputStream outputStream = prepareConnectionForBodyAndGetOutputStream(connection, contentLength);
|
||||
if (contentLength > 0) {
|
||||
outputStream.write(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void addBody(HttpURLConnection connection, MultipartPayload multipartPayload, boolean requiresBody)
|
||||
throws IOException {
|
||||
|
||||
for (Map.Entry<String, String> header : multipartPayload.getHeaders().entrySet()) {
|
||||
connection.setRequestProperty(header.getKey(), header.getValue());
|
||||
}
|
||||
|
||||
if (requiresBody) {
|
||||
final ByteArrayOutputStream os = MultipartUtils.getPayload(multipartPayload);
|
||||
final int contentLength = os.size();
|
||||
connection.setDoOutput(true);
|
||||
final OutputStream outputStream = prepareConnectionForBodyAndGetOutputStream(connection, contentLength);
|
||||
if (contentLength > 0) {
|
||||
os.writeTo(outputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static OutputStream prepareConnectionForBodyAndGetOutputStream(HttpURLConnection connection,
|
||||
int contentLength) throws IOException {
|
||||
connection.setRequestProperty(CONTENT_LENGTH, String.valueOf(contentLength));
|
||||
if (connection.getRequestProperty(CONTENT_TYPE) == null) {
|
||||
connection.setRequestProperty(CONTENT_TYPE, DEFAULT_CONTENT_TYPE);
|
||||
}
|
||||
return connection.getOutputStream();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
// 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.httpclient.jdk.JDKHttpClientConfig;
|
||||
import com.github.scribejava.core.model.*;
|
||||
import com.github.scribejava.core.oauth.OAuth10aService;
|
||||
import net.osmand.PlatformUtil;
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
/**
|
||||
* An OAuth 1.0 authorization client.
|
||||
*
|
||||
* @since 2746
|
||||
*/
|
||||
public class OsmOAuthAuthorizationClient {
|
||||
private OAuth1RequestToken requestToken;
|
||||
private OAuth1AccessToken accessToken;
|
||||
private final OAuth10aService service;
|
||||
private final OsmAndJDKHttpClient httpClient;
|
||||
public final static Log log = PlatformUtil.getLog(OsmOAuthAuthorizationClient.class);
|
||||
|
||||
public OsmOAuthAuthorizationClient(String key, String secret) {
|
||||
httpClient = new OsmAndJDKHttpClient(JDKHttpClientConfig.defaultConfig());
|
||||
service = new ServiceBuilder(key)
|
||||
.apiSecret(secret)
|
||||
.httpClient(httpClient)
|
||||
.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 OsmAndJDKHttpClient getHttpClient() {
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
public OAuth10aService getService() {
|
||||
return service;
|
||||
}
|
||||
|
||||
public void setAccessToken(OAuth1AccessToken accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
public OAuth1AccessToken getAccessToken() {
|
||||
return 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<Response> 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);
|
||||
}
|
||||
|
||||
public OAuth1RequestToken startOAuth() {
|
||||
try {
|
||||
requestToken = service.getRequestToken();
|
||||
} catch (IOException e) {
|
||||
log.error(e);
|
||||
} catch (InterruptedException e) {
|
||||
log.error(e);
|
||||
} catch (ExecutionException e) {
|
||||
log.error(e);
|
||||
}
|
||||
return requestToken;
|
||||
}
|
||||
|
||||
public OAuth1AccessToken authorize(String oauthVerifier) {
|
||||
try {
|
||||
setAccessToken(service.getAccessToken(requestToken, oauthVerifier));
|
||||
} catch (IOException e) {
|
||||
log.error(e);
|
||||
} catch (InterruptedException e) {
|
||||
log.error(e);
|
||||
} catch (ExecutionException e) {
|
||||
log.error(e);
|
||||
}
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public boolean isValidToken() {
|
||||
return !(accessToken == null);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
|
||||
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.STORAGE" />
|
||||
|
@ -52,7 +52,7 @@
|
|||
<application android:allowBackup="true" android:backupAgent="net.osmand.plus.OsmandBackupAgent"
|
||||
android:icon="@mipmap/icon" android:label="@string/app_name"
|
||||
android:name="net.osmand.plus.OsmandApplication" android:configChanges="locale"
|
||||
android:theme="@style/OsmandDarkTheme" android:restoreAnyVersion="true" android:largeHeap="true"
|
||||
android:theme="@style/OsmandDarkTheme" android:restoreAnyVersion="true" android:largeHeap="true"
|
||||
android:supportsRtl="true" android:usesCleartextTraffic="true">
|
||||
|
||||
<meta-data android:name="com.google.android.backup.api_key" android:value="AEdPqrEAAAAIqF3tNGT66etVBn_vgzpfAY1wmIzKV1Ss6Ku-2A" />
|
||||
|
@ -65,7 +65,7 @@
|
|||
<meta-data android:name="com.sec.minimode.icon.landscape.normal" android:resource="@mipmap/icon" android:value="" />
|
||||
<activity android:name="net.osmand.plus.activities.HelpActivity" />
|
||||
<activity android:name="net.osmand.plus.activities.ExitActivity" />
|
||||
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="net.osmand.plus.fileprovider"
|
||||
|
@ -479,7 +479,16 @@
|
|||
<activity android:name="net.osmand.plus.activities.SettingsNavigationActivity" android:configChanges="keyboardHidden|orientation" />
|
||||
<activity android:name="net.osmand.plus.monitoring.SettingsMonitoringActivity" android:configChanges="keyboardHidden|orientation" />
|
||||
|
||||
<activity android:name="net.osmand.plus.osmedit.SettingsOsmEditingActivity" android:configChanges="keyboardHidden|orientation" />
|
||||
<activity android:name="net.osmand.plus.osmedit.SettingsOsmEditingActivity"
|
||||
android:launchMode="singleInstance"
|
||||
android:configChanges="keyboardHidden|orientation">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="osmand-oauth" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="net.osmand.plus.development.SettingsDevelopmentActivity" android:configChanges="keyboardHidden|orientation" />
|
||||
<activity android:name="net.osmand.plus.audionotes.SettingsAudioVideoActivity" android:configChanges="keyboardHidden|orientation" />
|
||||
<activity android:name="net.osmand.access.SettingsAccessibilityActivity" android:configChanges="keyboardHidden|orientation" />
|
||||
|
@ -1025,7 +1034,7 @@
|
|||
|
||||
<!-- keep android:process on a separate line !! -->
|
||||
<service
|
||||
android:process="net.osmand.plus"
|
||||
android:process="net.osmand.plus"
|
||||
android:label="@string/process_navigation_service"
|
||||
android:name="net.osmand.plus.NavigationService"
|
||||
android:foregroundServiceType="location"
|
||||
|
|
|
@ -227,9 +227,13 @@ android {
|
|||
|
||||
buildTypes {
|
||||
debug {
|
||||
buildConfigField "String", "OSM_OAUTH_CONSUMER_KEY", "\"Ti2qq3fo4i4Wmuox3SiWRIGq3obZisBHnxmcM05y\""
|
||||
buildConfigField "String", "OSM_OAUTH_CONSUMER_SECRET", "\"lxulb3HYoMmd2cC4xxNe1dyfRMAY8dS0eNihJ0DM\""
|
||||
signingConfig signingConfigs.development
|
||||
}
|
||||
release {
|
||||
buildConfigField "String", "OSM_OAUTH_CONSUMER_KEY", "\"Ti2qq3fo4i4Wmuox3SiWRIGq3obZisBHnxmcM05y\""
|
||||
buildConfigField "String", "OSM_OAUTH_CONSUMER_SECRET", "\"lxulb3HYoMmd2cC4xxNe1dyfRMAY8dS0eNihJ0DM\""
|
||||
if (gradle.startParameter.taskNames.toString().contains("huawei")) {
|
||||
signingConfig signingConfigs.publishingHuawei
|
||||
} else {
|
||||
|
@ -532,6 +536,9 @@ dependencies {
|
|||
implementation ("com.github.HITGIF:TextFieldBoxes:1.4.5"){
|
||||
exclude group: 'com.android.support'
|
||||
}
|
||||
implementation('com.github.scribejava:scribejava-apis:7.1.1'){
|
||||
exclude group: "com.fasterxml.jackson.core"
|
||||
}
|
||||
implementation 'com.jaredrummler:colorpicker:1.1.0'
|
||||
|
||||
freehuaweiImplementation 'com.huawei.hms:iap:5.0.2.300'
|
||||
|
|
|
@ -11,6 +11,10 @@
|
|||
Thx - Hardy
|
||||
|
||||
-->
|
||||
<string name="osm_edit_logout_success">Logout successful</string>
|
||||
<string name="clear_osm_token">Clear OpenStreetMap OAuth token</string>
|
||||
<string name="perform_oauth_authorization">Log in via OAuth</string>
|
||||
<string name="perform_oauth_authorization_description">Perform an OAuth Login to use osmedit features</string>
|
||||
<string name="use_native_pt_desc">Switch to Java (safe) Public Transport routing calculation</string>
|
||||
<string name="use_native_pt">Native Public Transport development</string>
|
||||
<string name="use_fast_recalculation_desc">Recalculates only the initial part of the route. Can be used for long trips.</string>
|
||||
|
|
|
@ -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;
|
||||
|
@ -58,8 +59,8 @@ public class DownloadIndexesThread {
|
|||
private ConcurrentLinkedQueue<IndexItem> indexItemDownloading = new ConcurrentLinkedQueue<IndexItem>();
|
||||
private IndexItem currentDownloadingItem = null;
|
||||
private int currentDownloadingItemProgress = 0;
|
||||
|
||||
private DownloadResources indexes;
|
||||
private static final int THREAD_ID = 10103;
|
||||
|
||||
public interface DownloadEvents {
|
||||
|
||||
|
@ -336,6 +337,7 @@ public class DownloadIndexesThread {
|
|||
|
||||
@Override
|
||||
protected DownloadResources doInBackground(Void... params) {
|
||||
TrafficStats.setThreadStatsTag(THREAD_ID);
|
||||
DownloadResources result = null;
|
||||
DownloadOsmandIndexesHelper.IndexFileList indexFileList = DownloadOsmandIndexesHelper.getIndexesList(ctx);
|
||||
if (indexFileList != null) {
|
||||
|
|
|
@ -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,6 +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.OsmOAuthAuthorizationAdapter;
|
||||
import net.osmand.plus.render.RenderingIcons;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
|
@ -39,9 +38,16 @@ public class EditPOIMenuController extends MenuController {
|
|||
public void buttonPressed() {
|
||||
MapActivity activity = getMapActivity();
|
||||
if (plugin != null && activity != null) {
|
||||
SendPoiDialogFragment sendPoiDialogFragment =
|
||||
SendPoiDialogFragment.createInstance(new OsmPoint[]{getOsmPoint()}, SendPoiDialogFragment.PoiUploaderType.SIMPLE);
|
||||
sendPoiDialogFragment.show(activity.getSupportFragmentManager(), SendPoiDialogFragment.TAG);
|
||||
OsmOAuthAuthorizationAdapter client = new OsmOAuthAuthorizationAdapter(activity.getMyApplication());
|
||||
if (client.isValidToken()){
|
||||
new SendPoiDialogFragment.SimpleProgressDialogPoiUploader(activity).
|
||||
showProgressDialog(new OsmPoint[] { getOsmPoint() }, false, false);
|
||||
}
|
||||
else {
|
||||
SendPoiDialogFragment sendPoiDialogFragment =
|
||||
SendPoiDialogFragment.createInstance(new OsmPoint[]{getOsmPoint()}, SendPoiDialogFragment.PoiUploaderType.SIMPLE);
|
||||
sendPoiDialogFragment.show(activity.getSupportFragmentManager(), SendPoiDialogFragment.TAG);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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,38 +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.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 {
|
||||
|
||||
|
@ -99,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<String, String> additionalData = new LinkedHashMap<String, String>();
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -112,53 +108,15 @@ 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) {
|
||||
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);
|
||||
Response response = client.performRequestWithoutAuth(url,requestMethod,requestBody);
|
||||
return response.getBody();
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
// that's tricky case why NPE is thrown to fix that problem httpClient could be used
|
||||
|
@ -173,6 +131,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;
|
||||
|
@ -206,12 +172,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) {
|
||||
log.error(e);
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,12 +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.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;
|
||||
|
@ -109,6 +109,7 @@ public class OsmBugsRemoteUtil implements OsmBugsUtil {
|
|||
|
||||
private OsmBugResult editingPOI(String url, String requestMethod, String userOperation,
|
||||
boolean anonymous) {
|
||||
OsmOAuthAuthorizationAdapter client = new OsmOAuthAuthorizationAdapter(app);
|
||||
OsmBugResult r = new OsmBugResult();
|
||||
try {
|
||||
HttpURLConnection connection = NetworkUtils.getHttpURLConnection(url);
|
||||
|
@ -118,8 +119,12 @@ public class OsmBugsRemoteUtil implements OsmBugsUtil {
|
|||
connection.setRequestProperty("User-Agent", Version.getFullVersion(app)); //$NON-NLS-1$
|
||||
|
||||
if (!anonymous) {
|
||||
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 (client.isValidToken()) {
|
||||
connection.addRequestProperty("Authorization", "OAuth " + client.getClient().getAccessToken().getToken());
|
||||
} 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$
|
||||
}
|
||||
}
|
||||
|
||||
connection.setDoInput(true);
|
||||
|
|
|
@ -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,7 +23,7 @@ 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;
|
||||
|
@ -44,22 +42,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;
|
||||
|
||||
|
||||
|
@ -465,7 +457,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;
|
||||
}
|
||||
|
|
|
@ -3,8 +3,10 @@ package net.osmand.plus.osmedit;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.StrictMode;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.DialogPreference;
|
||||
import android.preference.Preference;
|
||||
|
@ -12,22 +14,40 @@ import android.preference.Preference.OnPreferenceClickListener;
|
|||
import android.preference.PreferenceScreen;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import net.osmand.plus.settings.backend.OsmAndAppCustomization;
|
||||
import com.github.scribejava.core.model.OAuthAsyncRequestCallback;
|
||||
import com.github.scribejava.core.model.Response;
|
||||
import net.osmand.PlatformUtil;
|
||||
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 org.apache.commons.logging.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class SettingsOsmEditingActivity extends SettingsBaseActivity {
|
||||
|
||||
private OsmOAuthAuthorizationAdapter client;
|
||||
private static final Log log = PlatformUtil.getLog(SettingsOsmEditingActivity.class);
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
|
||||
.detectDiskReads()
|
||||
.detectDiskWrites()
|
||||
.detectNetwork()
|
||||
.penaltyLog()
|
||||
.build());
|
||||
|
||||
((OsmandApplication) getApplication()).applyTheme(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
client = new OsmOAuthAuthorizationAdapter(getMyApplication());
|
||||
|
||||
getToolbar().setTitle(R.string.osm_settings);
|
||||
@SuppressWarnings("deprecation")
|
||||
PreferenceScreen grp = getPreferenceScreen();
|
||||
|
@ -39,7 +59,7 @@ public class SettingsOsmEditingActivity extends SettingsBaseActivity {
|
|||
R.string.offline_edition, R.string.offline_edition_descr);
|
||||
grp.addPreference(poiEdit);
|
||||
|
||||
Preference pref = new Preference(this);
|
||||
final Preference pref = new Preference(this);
|
||||
pref.setTitle(R.string.local_openstreetmap_settings);
|
||||
pref.setSummary(R.string.local_openstreetmap_settings_descr);
|
||||
pref.setKey("local_openstreetmap_points");
|
||||
|
@ -56,6 +76,44 @@ public class SettingsOsmEditingActivity extends SettingsBaseActivity {
|
|||
}
|
||||
});
|
||||
grp.addPreference(pref);
|
||||
|
||||
final Preference prefOAuth = new Preference(this);
|
||||
if (client.isValidToken()){
|
||||
prefOAuth.setTitle(R.string.osm_authorization_success);
|
||||
prefOAuth.setSummary(R.string.osm_authorization_success);
|
||||
prefOAuth.setKey("local_openstreetmap_oauth_success");
|
||||
final Preference prefClearToken = new Preference(this);
|
||||
prefClearToken.setTitle(R.string.shared_string_logoff);
|
||||
prefClearToken.setSummary(R.string.clear_osm_token);
|
||||
prefClearToken.setKey("local_openstreetmap_oauth_clear");
|
||||
prefClearToken.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
settings.USER_ACCESS_TOKEN.set("");
|
||||
settings.USER_ACCESS_TOKEN_SECRET.set("");
|
||||
client.resetToken();
|
||||
Toast.makeText(SettingsOsmEditingActivity.this, R.string.osm_edit_logout_success, Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
startActivity(getIntent());
|
||||
return true;
|
||||
}
|
||||
});
|
||||
grp.addPreference(prefClearToken);
|
||||
}
|
||||
else {
|
||||
prefOAuth.setTitle(R.string.perform_oauth_authorization);
|
||||
prefOAuth.setSummary(R.string.perform_oauth_authorization_description);
|
||||
prefOAuth.setKey("local_openstreetmap_oauth_login");
|
||||
prefOAuth.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
ViewGroup preferenceView = (ViewGroup)getListView().getChildAt(preference.getOrder());
|
||||
client.startOAuth(preferenceView);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
grp.addPreference(prefOAuth);
|
||||
}
|
||||
|
||||
public class OsmLoginDataDialogPreference extends DialogPreference {
|
||||
|
@ -116,4 +174,17 @@ public class SettingsOsmEditingActivity extends SettingsBaseActivity {
|
|||
Toast.makeText(context, text, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
Uri uri = intent.getData();
|
||||
System.out.println("URI=" + uri);
|
||||
if (uri != null && uri.toString().startsWith("osmand-oauth")) {
|
||||
String oauthVerifier = uri.getQueryParameter("oauth_verifier");
|
||||
client.authorize(oauthVerifier);
|
||||
finish();
|
||||
startActivity(getIntent());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package net.osmand.plus.osmedit;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.net.TrafficStats;
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import net.osmand.osm.edit.Entity;
|
||||
|
@ -24,6 +25,7 @@ public class UploadOpenstreetmapPointAsyncTask
|
|||
private OsmEditingPlugin plugin;
|
||||
private final boolean closeChangeSet;
|
||||
private final boolean loadAnonymous;
|
||||
private static final int THREAD_ID = 10102;
|
||||
|
||||
public UploadOpenstreetmapPointAsyncTask(ProgressDialogFragment progress,
|
||||
OsmEditsUploadListener listener,
|
||||
|
@ -43,6 +45,8 @@ public class UploadOpenstreetmapPointAsyncTask
|
|||
|
||||
@Override
|
||||
protected Map<OsmPoint, String> doInBackground(OsmPoint... points) {
|
||||
TrafficStats.setThreadStatsTag(THREAD_ID);
|
||||
|
||||
Map<OsmPoint, String> loadErrorsMap = new HashMap<>();
|
||||
|
||||
boolean uploaded = false;
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
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 {
|
||||
private OsmandApplication application;
|
||||
private OsmOAuthAuthorizationClient client =
|
||||
new OsmOAuthAuthorizationClient(BuildConfig.OSM_OAUTH_CONSUMER_KEY, BuildConfig.OSM_OAUTH_CONSUMER_SECRET);
|
||||
private static final int THREAD_ID = 10101;
|
||||
|
||||
public OsmOAuthAuthorizationAdapter(OsmandApplication application) {
|
||||
TrafficStats.setThreadStatsTag(THREAD_ID);
|
||||
this.application = application;
|
||||
restoreToken();
|
||||
}
|
||||
|
||||
public OsmOAuthAuthorizationClient getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
public boolean isValidToken() {
|
||||
return client.isValidToken();
|
||||
}
|
||||
|
||||
public void resetToken() {
|
||||
client.setAccessToken(null);
|
||||
}
|
||||
|
||||
public void restoreToken() {
|
||||
String token = application.getSettings().USER_ACCESS_TOKEN.get();
|
||||
String tokenSecret = application.getSettings().USER_ACCESS_TOKEN_SECRET.get();
|
||||
if (!(token.isEmpty() || tokenSecret.isEmpty())) {
|
||||
client.setAccessToken(new OAuth1AccessToken(token, tokenSecret));
|
||||
} else {
|
||||
client.setAccessToken(null);
|
||||
}
|
||||
}
|
||||
|
||||
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<Response> 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();
|
||||
}
|
||||
}
|
|
@ -1125,6 +1125,12 @@ public class OsmandSettings {
|
|||
public final OsmandPreference<String> USER_PASSWORD =
|
||||
new StringPreference(this, "user_password", "").makeGlobal();
|
||||
|
||||
public final OsmandPreference<String> USER_ACCESS_TOKEN =
|
||||
new StringPreference("user_access_token", "").makeGlobal();
|
||||
|
||||
public final OsmandPreference<String> USER_ACCESS_TOKEN_SECRET =
|
||||
new StringPreference("user_access_token_secret", "").makeGlobal();
|
||||
|
||||
// this value boolean is synchronized with settings_pref.xml preference offline POI/Bugs edition
|
||||
public final OsmandPreference<Boolean> OFFLINE_EDITION = new BooleanPreference(this, "offline_osm_editing", true).makeGlobal();
|
||||
|
||||
|
|
Loading…
Reference in a new issue