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 28a1ec3fb9..f95e3b4b45 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 @@ -56,6 +56,55 @@ public class NetworkUtils { return e.getMessage(); } } + + public static String sendPostDataRequest(String urlText, InputStream data) { + try { + log.info("POST : " + urlText); + HttpURLConnection conn = getHttpURLConnection(urlText); + conn.setDoInput(true); + conn.setDoOutput(false); + conn.setRequestMethod("POST"); + conn.setRequestProperty("Accept", "*/*"); + conn.setRequestProperty("User-Agent", "OsmAnd"); //$NON-NLS-1$ //$NON-NLS-2$ + conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); + OutputStream ous = conn.getOutputStream(); + ous.write(("--" + BOUNDARY + "\r\n").getBytes()); + ous.write(("content-disposition: form-data; name=\"" + "file" + "\"; filename=\"" + "image1" + "\"\r\n").getBytes()); //$NON-NLS-1$ //$NON-NLS-2$ + ous.write(("Content-Type: application/octet-stream\r\n\r\n").getBytes()); //$NON-NLS-1$ + Algorithms.streamCopy(data, ous); + ous.write(("\r\n--" + BOUNDARY + "--\r\n").getBytes()); //$NON-NLS-1$ //$NON-NLS-2$ + ous.flush(); + log.info("Response code and message : " + conn.getResponseCode() + " " + conn.getResponseMessage()); + if (conn.getResponseCode() != 200) { + return null; + } + StringBuilder responseBody = new StringBuilder(); + InputStream is = conn.getInputStream(); + responseBody.setLength(0); + if (is != null) { + BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8")); //$NON-NLS-1$ + String s; + boolean first = true; + while ((s = in.readLine()) != null) { + if (first) { + first = false; + } else { + responseBody.append("\n"); //$NON-NLS-1$ + } + responseBody.append(s); + } + is.close(); + } + Algorithms.closeStream(is); + Algorithms.closeStream(data); + Algorithms.closeStream(ous); + return responseBody.toString(); + } catch (IOException e) { + log.error(e.getMessage(), e); + return e.getMessage(); + } + } + private static final String BOUNDARY = "CowMooCowMooCowCowCow"; //$NON-NLS-1$ public static String uploadFile(String urlText, File fileToUpload, String userNamePassword, OsmOAuthAuthorizationClient client, diff --git a/OsmAnd/build.gradle b/OsmAnd/build.gradle index c52dac72ad..91ec5744e0 100644 --- a/OsmAnd/build.gradle +++ b/OsmAnd/build.gradle @@ -526,4 +526,6 @@ dependencies { implementation 'com.jaredrummler:colorpicker:1.1.0' freehuaweiImplementation 'com.huawei.hms:iap:5.0.2.300' + + implementation "org.bouncycastle:bcpkix-jdk15on:1.56" } diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/ImageCard.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/ImageCard.java index 26c81f03a7..d7b1d69895 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/ImageCard.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/ImageCard.java @@ -509,6 +509,7 @@ public abstract class ImageCard extends AbstractCard { "Requesting location images...", false, false); try { if (!Algorithms.isEmpty(response)) { + //TODO extract place id JSONArray obj = new JSONObject(response).getJSONArray("objects"); JSONArray images = ((JSONObject) ((JSONObject) obj.get(0)).get("images")).getJSONArray("outdoor"); if (images.length() > 0) { diff --git a/OsmAnd/src/net/osmand/plus/osmedit/opr/OpenDBAPI.java b/OsmAnd/src/net/osmand/plus/osmedit/opr/OpenDBAPI.java new file mode 100644 index 0000000000..550906a508 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/osmedit/opr/OpenDBAPI.java @@ -0,0 +1,107 @@ +package net.osmand.plus.osmedit.opr; + +import android.net.TrafficStats; +import android.os.Build; +import com.google.gson.GsonBuilder; +import net.osmand.PlatformUtil; +import net.osmand.plus.BuildConfig; +import org.apache.commons.logging.Log; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.openplacereviews.opendb.SecUtils; +import org.openplacereviews.opendb.ops.OpOperation; +import org.openplacereviews.opendb.util.JsonFormatter; +import org.openplacereviews.opendb.util.exception.FailedVerificationException; + +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.security.KeyPair; +import java.security.Security; +import java.util.*; + +import static org.openplacereviews.opendb.SecUtils.*; + + +public class OpenDBAPI { + private static final Log log = PlatformUtil.getLog(SecUtils.class); + + private static final int THREAD_ID = 11200; + + public int uploadImage(String[] placeId, String privateKey, String username, String image) throws FailedVerificationException { + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + Security.removeProvider("BC"); + Security.addProvider(new BouncyCastleProvider()); + } + KeyPair kp = SecUtils.getKeyPair(ALGO_EC, privateKey, null); + String signed = username;// + ":opr-web"; + + JsonFormatter formatter = new JsonFormatter(); + OPRImage OPRImage = new GsonBuilder().create().fromJson(image, OPRImage.class); + OpOperation opOperation = new OpOperation(); + opOperation.setType("opr.place"); + List edits = new ArrayList<>(); + Map edit = new TreeMap<>(); + List imageResponseList = new ArrayList<>(); + Map imageMap = new TreeMap<>(); + imageMap.put("cid", OPRImage.cid); + imageMap.put("hash", OPRImage.hash); + imageMap.put("extension", OPRImage.extension); + imageMap.put("type", OPRImage.type); + imageResponseList.add(imageMap); + List ids = new ArrayList<>(Arrays.asList(placeId)); + Map change = new TreeMap<>(); + Map images = new TreeMap<>(); + Map outdoor = new TreeMap<>(); + outdoor.put("outdoor", imageResponseList); + images.put("append", outdoor); + change.put("version", "increment"); + change.put("images", images); + edit.put("id", ids); + edit.put("change", change); + edit.put("current", new Object()); + edits.add(edit); + opOperation.putObjectValue(OpOperation.F_EDIT, edits); + opOperation.setSignedBy(signed); + String hash = JSON_MSG_TYPE + ":" + + SecUtils.calculateHashWithAlgo(SecUtils.HASH_SHA256, null, + formatter.opToJsonNoHash(opOperation)); + byte[] hashBytes = SecUtils.getHashBytes(hash); + String signature = signMessageWithKeyBase64(kp, hashBytes, SecUtils.SIG_ALGO_SHA1_EC, null); + opOperation.addOrSetStringValue("hash", hash); + opOperation.addOrSetStringValue("signature", signature); + TrafficStats.setThreadStatsTag(THREAD_ID); + String url = BuildConfig.OPR_BASE_URL + "api/auth/process-operation?addToQueue=true&dontSignByServer=false"; + String json = formatter.opToJson(opOperation); + System.out.println("JSON: " + json); + HttpURLConnection connection; + try { + connection = (HttpURLConnection) new URL(url).openConnection(); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setConnectTimeout(10000); + connection.setRequestMethod("POST"); + connection.setDoOutput(true); + try { + DataOutputStream wr = new DataOutputStream(connection.getOutputStream()); + wr.write(json.getBytes()); + } catch (Exception e) { + e.printStackTrace(); + } + int rc = connection.getResponseCode(); + if (rc != 200) { + log.error("ERROR HAPPENED"); + BufferedReader br = new BufferedReader(new InputStreamReader(connection.getErrorStream())); + String strCurrentLine; + while ((strCurrentLine = br.readLine()) != null) { + log.error(strCurrentLine); + } + } + return rc; + } catch (IOException e) { + log.error(e); + } + return -1; + } +} \ No newline at end of file