package app.fedilab.android.client; /* Copyright 2017 Thomas Schneider * * This file is a part of Fedilab * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; either version 3 of the * License, or (at your option) any later version. * * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along with Fedilab; if not, * see . */ import android.content.Context; import android.content.SharedPreferences; import android.os.Build; import android.text.Html; import android.text.SpannableString; import com.google.gson.JsonObject; import net.gotev.uploadservice.MultipartUploadRequest; import net.gotev.uploadservice.ServerResponse; import net.gotev.uploadservice.UploadInfo; import net.gotev.uploadservice.UploadNotificationConfig; import net.gotev.uploadservice.UploadStatusDelegate; import org.apache.poi.util.IOUtils; import org.json.JSONObject; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Authenticator; import java.net.HttpURLConnection; import java.net.InetSocketAddress; import java.net.MalformedURLException; import java.net.PasswordAuthentication; import java.net.Proxy; import java.net.URL; import java.nio.charset.StandardCharsets; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.net.ssl.HttpsURLConnection; import app.fedilab.android.R; import app.fedilab.android.activities.MainActivity; import app.fedilab.android.activities.SlideMediaActivity; import app.fedilab.android.activities.TootActivity; import app.fedilab.android.asynctasks.UpdateAccountInfoAsyncTask; import app.fedilab.android.client.Entities.Error; import app.fedilab.android.helper.FileNameCleaner; import app.fedilab.android.helper.Helper; import app.fedilab.android.interfaces.OnDownloadInterface; import static app.fedilab.android.helper.Helper.urlPattern; /** * Created by Thomas on 17/11/2017. * Manage http queries */ public class HttpsConnection { private HttpURLConnection httpURLConnection; private String since_id, max_id; private final Context context; private final int CHUNK_SIZE = 4096; private final SharedPreferences sharedpreferences; private Proxy proxy; private final String instance; private final String USER_AGENT; public HttpsConnection(Context context, String instance) { this.instance = instance; this.context = context; sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); boolean proxyEnabled = sharedpreferences.getBoolean(Helper.SET_PROXY_ENABLED, false); int type = sharedpreferences.getInt(Helper.SET_PROXY_TYPE, 0); proxy = null; USER_AGENT = sharedpreferences.getString(Helper.SET_CUSTOM_USER_AGENT, Helper.USER_AGENT); if (proxyEnabled) { try { String host = sharedpreferences.getString(Helper.SET_PROXY_HOST, "127.0.0.1"); int port = sharedpreferences.getInt(Helper.SET_PROXY_PORT, 8118); if (type == 0) proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(host, port)); else proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(host, port)); final String login = sharedpreferences.getString(Helper.SET_PROXY_LOGIN, null); final String pwd = sharedpreferences.getString(Helper.SET_PROXY_PASSWORD, null); if (login != null) { Authenticator authenticator = new Authenticator() { public PasswordAuthentication getPasswordAuthentication() { assert pwd != null; return (new PasswordAuthentication(login, pwd.toCharArray())); } }; Authenticator.setDefault(authenticator); } } catch (Exception e) { proxy = null; } } if (instance != null && instance.endsWith(".onion")) { HttpsURLConnection.setDefaultHostnameVerifier((arg0, arg1) -> true); } } private void setToken(MultipartUploadRequest multipartUploadRequest, String token) { if (token != null) { if (token.startsWith("Basic ")) multipartUploadRequest.addHeader("Authorization", token); else if (token.startsWith("X-XSRF-TOKEN")) { String cookie = token.split("\\|")[1]; multipartUploadRequest.addHeader("cookie", cookie); String[] tokens = token.split("\\|")[0].split(";"); multipartUploadRequest.addHeader("x-xsrf-token", tokens[0].replace("X-XSRF-TOKEN= ", "")); multipartUploadRequest.addHeader("x-csrf-token", tokens[1].replace("X-CSRF-TOKEN= ", "")); } else multipartUploadRequest.addHeader("Authorization", "Bearer " + token); } } private void setToken(String token) { if (token != null) { if (token.startsWith("Basic ")) httpURLConnection.setRequestProperty("Authorization", token); else if (token.startsWith("X-XSRF-TOKEN")) { String cookie = token.split("\\|")[1]; httpURLConnection.setRequestProperty("cookie", cookie); String[] tokens = token.split("\\|")[0].split(";"); httpURLConnection.setRequestProperty("x-xsrf-token", tokens[0].replace("X-XSRF-TOKEN= ", "")); httpURLConnection.setRequestProperty("x-csrf-token", tokens[1].replace("X-CSRF-TOKEN= ", "")); } else httpURLConnection.setRequestProperty("Authorization", "Bearer " + token); } } /** * Get calls * * @param urlConnection String url * @param timeout int timeout * @param paramaters HashMap paramaters * @param token String token * @return String * @throws IOException IOException * @throws NoSuchAlgorithmException NoSuchAlgorithmException * @throws KeyManagementException KeyManagementException * @throws HttpsConnectionException HttpsConnectionException */ public String get(String urlConnection, int timeout, HashMap paramaters, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException { Map params = new LinkedHashMap<>(); if (paramaters != null) { Iterator> it = paramaters.entrySet().iterator(); while (it.hasNext()) { Map.Entry pair = it.next(); params.put(pair.getKey(), pair.getValue()); it.remove(); } } StringBuilder postData = new StringBuilder(); URL url; if (params.size() > 0) { for (Map.Entry param : params.entrySet()) { if (postData.length() != 0) postData.append('&'); postData.append(param.getKey()); postData.append('='); postData.append(param.getValue()); } url = new URL(urlConnection + "?" + postData); } else { url = new URL(urlConnection); } if (proxy != null) httpURLConnection = (HttpsURLConnection) url.openConnection(proxy); else httpURLConnection = (HttpsURLConnection) url.openConnection(); httpURLConnection.setConnectTimeout(timeout * 1000); httpURLConnection.setRequestProperty("http.keepAlive", "false"); httpURLConnection.setRequestProperty("User-Agent", USER_AGENT); httpURLConnection.setRequestProperty("Content-Type", "application/json"); httpURLConnection.setRequestProperty("Accept", "application/json"); httpURLConnection.setUseCaches(true); httpURLConnection.setDefaultUseCaches(true); if (httpURLConnection instanceof HttpsURLConnection) { ((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(new TLSSocketFactory(this.instance)); } setToken(token); httpURLConnection.setRequestMethod("GET"); String response; if (httpURLConnection.getResponseCode() >= 200 && httpURLConnection.getResponseCode() < 400) { response = converToString(httpURLConnection.getInputStream()); } else { String error = null; if (httpURLConnection.getErrorStream() != null) { InputStream stream = httpURLConnection.getErrorStream(); if (stream == null) { stream = httpURLConnection.getInputStream(); } try (Scanner scanner = new Scanner(stream)) { scanner.useDelimiter("\\Z"); if (scanner.hasNext()) { error = scanner.next(); } } catch (Exception e) { e.printStackTrace(); } } int responseCode = httpURLConnection.getResponseCode(); try { httpURLConnection.getInputStream().close(); } catch (Exception ignored) { } throw new HttpsConnectionException(responseCode, error); } getSinceMaxId(); httpURLConnection.getInputStream().close(); return response; } /** * Will check if the current url is redirecting * * @param urlConnection String the url to check * @return String null|string url redirection */ public String checkUrl(String urlConnection) { URL url; String redirect = null; try { url = new URL(urlConnection); if (proxy != null) httpURLConnection = (HttpsURLConnection) url.openConnection(proxy); else httpURLConnection = (HttpsURLConnection) url.openConnection(); httpURLConnection.setRequestProperty("http.keepAlive", "false"); httpURLConnection.setInstanceFollowRedirects(false); if (httpURLConnection instanceof HttpsURLConnection) { ((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(new TLSSocketFactory(this.instance)); } httpURLConnection.setRequestMethod("HEAD"); if (httpURLConnection.getResponseCode() == 301 || httpURLConnection.getResponseCode() == 302) { Map> map = httpURLConnection.getHeaderFields(); for (Map.Entry> entry : map.entrySet()) { if (entry.toString().toLowerCase().startsWith("location")) { Matcher matcher = urlPattern.matcher(entry.toString()); if (matcher.find()) { redirect = matcher.group(1); } } } } httpURLConnection.getInputStream().close(); if (redirect != null && redirect.compareTo(urlConnection) != 0) { URL redirectURL = new URL(redirect); String host = redirectURL.getHost(); String protocol = redirectURL.getProtocol(); if (protocol == null || host == null) { redirect = null; } } return redirect; } catch (IOException | NoSuchAlgorithmException | KeyManagementException e) { e.printStackTrace(); } return null; } public String get(String urlConnection) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException { URL url = new URL(urlConnection); if (proxy != null) httpURLConnection = (HttpURLConnection) url.openConnection(proxy); else httpURLConnection = (HttpURLConnection) url.openConnection(); httpURLConnection.setConnectTimeout(30 * 1000); httpURLConnection.setRequestProperty("http.keepAlive", "false"); httpURLConnection.setRequestProperty("Content-Type", "application/json"); httpURLConnection.setRequestProperty("Accept", "application/json"); httpURLConnection.setRequestProperty("User-Agent", USER_AGENT); if (httpURLConnection instanceof HttpsURLConnection) { ((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(new TLSSocketFactory(this.instance)); } httpURLConnection.setRequestMethod("GET"); httpURLConnection.setDefaultUseCaches(true); httpURLConnection.setUseCaches(true); String response; if (httpURLConnection.getResponseCode() >= 200 && httpURLConnection.getResponseCode() < 400) { getSinceMaxId(); response = converToString(httpURLConnection.getInputStream()); } else { String error = null; if (httpURLConnection.getErrorStream() != null) { InputStream stream = httpURLConnection.getErrorStream(); if (stream == null) { stream = httpURLConnection.getInputStream(); } try (Scanner scanner = new Scanner(stream)) { scanner.useDelimiter("\\Z"); if (scanner.hasNext()) { error = scanner.next(); } } catch (Exception e) { e.printStackTrace(); } } int responseCode = httpURLConnection.getResponseCode(); try { httpURLConnection.getInputStream().close(); } catch (Exception ignored) { } throw new HttpsConnectionException(responseCode, error); } getSinceMaxId(); httpURLConnection.getInputStream().close(); return response; } public String post(String urlConnection, int timeout, HashMap paramaters, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException { URL url = new URL(urlConnection); Map params = new LinkedHashMap<>(); if (paramaters != null) { Iterator> it = paramaters.entrySet().iterator(); while (it.hasNext()) { Map.Entry pair = it.next(); params.put(pair.getKey(), pair.getValue()); it.remove(); } } StringBuilder postData = new StringBuilder(); for (Map.Entry param : params.entrySet()) { if (postData.length() != 0) postData.append('&'); postData.append(param.getKey()); postData.append('='); postData.append(param.getValue()); } byte[] postDataBytes = postData.toString().getBytes(StandardCharsets.UTF_8); if (proxy != null) httpURLConnection = (HttpsURLConnection) url.openConnection(proxy); else httpURLConnection = (HttpsURLConnection) url.openConnection(); httpURLConnection.setRequestProperty("User-Agent", USER_AGENT); httpURLConnection.setConnectTimeout(timeout * 1000); httpURLConnection.setDoOutput(true); if (httpURLConnection instanceof HttpsURLConnection) { ((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(new TLSSocketFactory(this.instance)); } httpURLConnection.setRequestMethod("POST"); setToken(token); httpURLConnection.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length)); httpURLConnection.getOutputStream().write(postDataBytes); String response; if (httpURLConnection.getResponseCode() >= 200 && httpURLConnection.getResponseCode() < 400) { getSinceMaxId(); response = converToString(httpURLConnection.getInputStream()); } else { String error = null; if (httpURLConnection.getErrorStream() != null) { InputStream stream = httpURLConnection.getErrorStream(); if (stream == null) { stream = httpURLConnection.getInputStream(); } try (Scanner scanner = new Scanner(stream)) { scanner.useDelimiter("\\Z"); if (scanner.hasNext()) { error = scanner.next(); } } catch (Exception e) { e.printStackTrace(); } } int responseCode = httpURLConnection.getResponseCode(); try { httpURLConnection.getInputStream().close(); } catch (Exception ignored) { } throw new HttpsConnectionException(responseCode, error); } getSinceMaxId(); httpURLConnection.getInputStream().close(); return response; } String postJson(String urlConnection, int timeout, JsonObject jsonObject, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException { URL url = new URL(urlConnection); byte[] postDataBytes; postDataBytes = jsonObject.toString().getBytes(StandardCharsets.UTF_8); if (proxy != null) httpURLConnection = (HttpURLConnection) url.openConnection(proxy); else httpURLConnection = (HttpURLConnection) url.openConnection(); httpURLConnection.setRequestProperty("User-Agent", USER_AGENT); httpURLConnection.setConnectTimeout(timeout * 1000); httpURLConnection.setDoOutput(true); if (httpURLConnection instanceof HttpsURLConnection) { ((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(new TLSSocketFactory(this.instance)); } httpURLConnection.setRequestProperty("Content-Type", "application/json"); httpURLConnection.setRequestProperty("Accept", "application/json"); httpURLConnection.setRequestMethod("POST"); setToken(token); httpURLConnection.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length)); httpURLConnection.getOutputStream().write(postDataBytes); String response; if (httpURLConnection.getResponseCode() >= 200 && httpURLConnection.getResponseCode() < 400) { getSinceMaxId(); response = converToString(httpURLConnection.getInputStream()); } else { String error = null; if (httpURLConnection.getErrorStream() != null) { InputStream stream = httpURLConnection.getErrorStream(); if (stream == null) { stream = httpURLConnection.getInputStream(); } try (Scanner scanner = new Scanner(stream)) { scanner.useDelimiter("\\Z"); if (scanner.hasNext()) { error = scanner.next(); } } catch (Exception e) { e.printStackTrace(); } } int responseCode = httpURLConnection.getResponseCode(); try { httpURLConnection.getInputStream().close(); } catch (Exception ignored) { } throw new HttpsConnectionException(responseCode, error); } getSinceMaxId(); httpURLConnection.getInputStream().close(); return response; } String postJson(String urlConnection, int timeout, JSONObject jsonObject, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException { URL url = new URL(urlConnection); byte[] postDataBytes; postDataBytes = jsonObject.toString().getBytes(StandardCharsets.UTF_8); if (proxy != null) httpURLConnection = (HttpURLConnection) url.openConnection(proxy); else httpURLConnection = (HttpURLConnection) url.openConnection(); httpURLConnection.setRequestProperty("User-Agent", USER_AGENT); httpURLConnection.setConnectTimeout(timeout * 1000); httpURLConnection.setDoOutput(true); if (httpURLConnection instanceof HttpsURLConnection) { ((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(new TLSSocketFactory(this.instance)); } httpURLConnection.setRequestProperty("Content-Type", "application/json"); httpURLConnection.setRequestProperty("Accept", "application/json"); httpURLConnection.setRequestMethod("POST"); setToken(token); httpURLConnection.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length)); httpURLConnection.getOutputStream().write(postDataBytes); String response; if (httpURLConnection.getResponseCode() >= 200 && httpURLConnection.getResponseCode() < 400) { getSinceMaxId(); response = converToString(httpURLConnection.getInputStream()); } else { String error = null; if (httpURLConnection.getErrorStream() != null) { InputStream stream = httpURLConnection.getErrorStream(); if (stream == null) { stream = httpURLConnection.getInputStream(); } try (Scanner scanner = new Scanner(stream)) { scanner.useDelimiter("\\Z"); if (scanner.hasNext()) { error = scanner.next(); } } catch (Exception e) { e.printStackTrace(); } } int responseCode = httpURLConnection.getResponseCode(); try { httpURLConnection.getInputStream().close(); } catch (Exception ignored) { } throw new HttpsConnectionException(responseCode, error); } getSinceMaxId(); httpURLConnection.getInputStream().close(); return response; } @SuppressWarnings("SameParameterValue") String postMisskey(String urlConnection, int timeout, JSONObject paramaters, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException { URL url = new URL(urlConnection); byte[] postDataBytes = paramaters.toString().getBytes(StandardCharsets.UTF_8); if (proxy != null) httpURLConnection = (HttpsURLConnection) url.openConnection(proxy); else httpURLConnection = (HttpsURLConnection) url.openConnection(); httpURLConnection.setRequestProperty("User-Agent", USER_AGENT); httpURLConnection.setConnectTimeout(timeout * 1000); httpURLConnection.setDoOutput(true); if (httpURLConnection instanceof HttpsURLConnection) { ((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(new TLSSocketFactory(this.instance)); } httpURLConnection.setRequestMethod("POST"); setToken(token); httpURLConnection.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length)); httpURLConnection.getOutputStream().write(postDataBytes); String response; if (httpURLConnection.getResponseCode() >= 200 && httpURLConnection.getResponseCode() < 400) { getSinceMaxId(); response = converToString(httpURLConnection.getInputStream()); } else { String error = null; if (httpURLConnection.getErrorStream() != null) { InputStream stream = httpURLConnection.getErrorStream(); if (stream == null) { stream = httpURLConnection.getInputStream(); } try (Scanner scanner = new Scanner(stream)) { scanner.useDelimiter("\\Z"); if (scanner.hasNext()) { error = scanner.next(); } } catch (Exception e) { e.printStackTrace(); } } int responseCode = httpURLConnection.getResponseCode(); try { httpURLConnection.getInputStream().close(); } catch (Exception ignored) { } throw new HttpsConnectionException(responseCode, error); } getSinceMaxId(); httpURLConnection.getInputStream().close(); return response; } /*** * Download method which works for http and https connections * @param downloadUrl String download url * @param listener OnDownloadInterface, listener which manages progress */ public void download(final String downloadUrl, final OnDownloadInterface listener) { new Thread(() -> { URL url; try { url = new URL(downloadUrl); if (proxy != null) httpURLConnection = (HttpURLConnection) url.openConnection(proxy); else httpURLConnection = (HttpURLConnection) url.openConnection(); httpURLConnection.setRequestProperty("User-Agent", USER_AGENT); int responseCode = httpURLConnection.getResponseCode(); // always check HTTP response code first if (responseCode == HttpURLConnection.HTTP_OK) { String fileName = ""; String disposition = httpURLConnection.getHeaderField("Content-Disposition"); if (disposition != null) { // extracts file name from header field int index = disposition.indexOf("filename="); if (index > 0) { fileName = disposition.substring(index + 10, disposition.length() - 1); } } else { // extracts file name from URL fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/") + 1 ); } fileName = FileNameCleaner.cleanFileName(fileName); // opens input stream from the HTTP connection InputStream inputStream = httpURLConnection.getInputStream(); File saveDir = context.getCacheDir(); final String saveFilePath = saveDir + File.separator + fileName; // opens an output stream to save into file FileOutputStream outputStream = new FileOutputStream(saveFilePath); int bytesRead; byte[] buffer = new byte[CHUNK_SIZE]; int contentSize = httpURLConnection.getContentLength(); int downloadedFileSize = 0; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); downloadedFileSize += bytesRead; if (context instanceof SlideMediaActivity) { final int currentProgress = (downloadedFileSize * 100) / contentSize; ((SlideMediaActivity) context).runOnUiThread(() -> listener.onUpdateProgress(currentProgress > 0 ? currentProgress : 101)); } } outputStream.close(); inputStream.close(); if (context instanceof TootActivity) ((TootActivity) context).runOnUiThread(() -> listener.onDownloaded(saveFilePath, downloadUrl, null)); if (context instanceof SlideMediaActivity) ((SlideMediaActivity) context).runOnUiThread(() -> listener.onDownloaded(saveFilePath, downloadUrl, null)); } else { final Error error = new Error(); error.setError(String.valueOf(responseCode)); if (context instanceof TootActivity) ((TootActivity) context).runOnUiThread(() -> listener.onDownloaded(null, downloadUrl, error)); if (context instanceof SlideMediaActivity) ((SlideMediaActivity) context).runOnUiThread(() -> listener.onDownloaded(null, downloadUrl, error)); } } catch (IOException e) { Error error = new Error(); error.setError(context.getString(R.string.toast_error)); } }).start(); } public InputStream getPicture(final String downloadUrl) { URL url; try { url = new URL(downloadUrl); } catch (MalformedURLException e) { return null; } try { if (proxy != null) httpURLConnection = (HttpsURLConnection) url.openConnection(proxy); else httpURLConnection = (HttpsURLConnection) url.openConnection(); if (httpURLConnection instanceof HttpsURLConnection) { ((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(new TLSSocketFactory(this.instance)); } httpURLConnection.setRequestProperty("User-Agent", USER_AGENT); if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { String token = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null); String cookie = token.split("\\|")[1]; httpURLConnection.setRequestProperty("Cookie", cookie); } int responseCode = httpURLConnection.getResponseCode(); // always check HTTP response code first if (responseCode >= 200 && responseCode < 400) { // opens input stream from the HTTP connection return httpURLConnection.getInputStream(); } httpURLConnection.getInputStream().close(); } catch (IOException | NoSuchAlgorithmException | KeyManagementException ignored) { } if (httpURLConnection != null) try { httpURLConnection.getInputStream().close(); } catch (Exception ignored) { } return null; } private void uploadMedia(String urlConnection, InputStream avatar, InputStream header, String filename) { UploadNotificationConfig uploadConfig = new UploadNotificationConfig(); uploadConfig.getCompleted().autoClear = true; File file = new File(context.getCacheDir() + "/" + filename); OutputStream outputStream; try { outputStream = new FileOutputStream(file); if (avatar != null) { IOUtils.copy(avatar, outputStream); } else { IOUtils.copy(header, outputStream); } } catch (IOException e) { e.printStackTrace(); } try { String token = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null); MultipartUploadRequest m = new MultipartUploadRequest(context, urlConnection) .setMethod("PATCH"); if (avatar != null) { m.addFileToUpload(file.getPath(), "avatar"); } else { m.addFileToUpload(file.getPath(), "header"); } MultipartUploadRequest multipartUploadRequest = m.addParameter("name", filename); setToken(multipartUploadRequest, token); multipartUploadRequest.setNotificationConfig(uploadConfig) .setDelegate(new UploadStatusDelegate() { @Override public void onProgress(Context context, UploadInfo uploadInfo) { // your code here } @Override public void onError(Context context, UploadInfo uploadInfo, ServerResponse serverResponse, Exception exception) { //noinspection ResultOfMethodCallIgnored file.delete(); } @Override public void onCompleted(Context context, UploadInfo uploadInfo, ServerResponse serverResponse) { //noinspection ResultOfMethodCallIgnored file.delete(); } @Override public void onCancelled(Context context, UploadInfo uploadInfo) { //noinspection ResultOfMethodCallIgnored file.delete(); } }) .startUpload(); } catch (MalformedURLException | FileNotFoundException e) { e.printStackTrace(); } } @SuppressWarnings("SameParameterValue") public String patch(String urlConnection, int timeout, HashMap paramaters, InputStream avatar, String avatarName, InputStream header, String headerName, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException { URL url = new URL(urlConnection); Map params = new LinkedHashMap<>(); if (paramaters != null) { Iterator> it = paramaters.entrySet().iterator(); while (it.hasNext()) { Map.Entry pair = it.next(); params.put(pair.getKey(), pair.getValue()); it.remove(); } } StringBuilder postData = new StringBuilder(); for (Map.Entry param : params.entrySet()) { if (postData.length() != 0) postData.append('&'); postData.append(param.getKey()); postData.append('='); postData.append(param.getValue()); } byte[] postDataBytes = (postData.toString()).getBytes(StandardCharsets.UTF_8); if (proxy != null) httpURLConnection = (HttpsURLConnection) url.openConnection(proxy); else httpURLConnection = (HttpsURLConnection) url.openConnection(); httpURLConnection.setRequestProperty("User-Agent", USER_AGENT); httpURLConnection.setConnectTimeout(timeout * 1000); if (httpURLConnection instanceof HttpsURLConnection) { ((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(new TLSSocketFactory(this.instance)); } httpURLConnection.setRequestMethod("PATCH"); setToken(token); httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); httpURLConnection.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length)); httpURLConnection.setDoOutput(true); String response; OutputStream outputStream = httpURLConnection.getOutputStream(); outputStream.write(postDataBytes); if (avatar != null) { uploadMedia(urlConnection, avatar, null, avatarName); } if (header != null) { uploadMedia(urlConnection, null, header, headerName); } if (httpURLConnection.getResponseCode() >= 200 && httpURLConnection.getResponseCode() < 400) { response = converToString(httpURLConnection.getInputStream()); } else { String error = null; if (httpURLConnection.getErrorStream() != null) { InputStream stream = httpURLConnection.getErrorStream(); if (stream == null) { stream = httpURLConnection.getInputStream(); } try (Scanner scanner = new Scanner(stream)) { scanner.useDelimiter("\\Z"); if (scanner.hasNext()) { error = scanner.next(); } } catch (Exception e) { e.printStackTrace(); } } int responseCode = httpURLConnection.getResponseCode(); try { httpURLConnection.getInputStream().close(); } catch (Exception ignored) { } try { httpURLConnection.getInputStream().close(); } catch (Exception ignored) { } throw new HttpsConnectionException(responseCode, error); } httpURLConnection.getInputStream().close(); return response; } public String put(String urlConnection, int timeout, HashMap paramaters, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException { URL url = new URL(urlConnection); Map params = new LinkedHashMap<>(); if (paramaters != null) { Iterator> it = paramaters.entrySet().iterator(); while (it.hasNext()) { Map.Entry pair = it.next(); params.put(pair.getKey(), pair.getValue()); it.remove(); } } StringBuilder postData = new StringBuilder(); for (Map.Entry param : params.entrySet()) { if (postData.length() != 0) postData.append('&'); postData.append(param.getKey()); postData.append('='); postData.append(param.getValue()); } byte[] postDataBytes = postData.toString().getBytes(StandardCharsets.UTF_8); if (proxy != null) httpURLConnection = (HttpsURLConnection) url.openConnection(proxy); else httpURLConnection = (HttpsURLConnection) url.openConnection(); httpURLConnection.setRequestProperty("User-Agent", USER_AGENT); httpURLConnection.setConnectTimeout(timeout * 1000); if (httpURLConnection instanceof HttpsURLConnection) { ((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(new TLSSocketFactory(this.instance)); } setToken(token); httpURLConnection.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length)); httpURLConnection.setRequestMethod("PUT"); httpURLConnection.setDoInput(true); httpURLConnection.setDoOutput(true); httpURLConnection.getOutputStream().write(postDataBytes); String response; if (httpURLConnection.getResponseCode() >= 200 && httpURLConnection.getResponseCode() < 400) { getSinceMaxId(); response = converToString(httpURLConnection.getInputStream()); } else { String error = null; if (httpURLConnection.getErrorStream() != null) { InputStream stream = httpURLConnection.getErrorStream(); if (stream == null) { stream = httpURLConnection.getInputStream(); } try (Scanner scanner = new Scanner(stream)) { scanner.useDelimiter("\\Z"); if (scanner.hasNext()) { error = scanner.next(); } } catch (Exception e) { e.printStackTrace(); } } int responseCode = httpURLConnection.getResponseCode(); try { httpURLConnection.getInputStream().close(); } catch (Exception ignored) { } throw new HttpsConnectionException(responseCode, error); } getSinceMaxId(); httpURLConnection.getInputStream().close(); return response; } public int delete(String urlConnection, int timeout, HashMap paramaters, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException { URL url = new URL(urlConnection); Map params = new LinkedHashMap<>(); if (paramaters != null) { Iterator> it = paramaters.entrySet().iterator(); while (it.hasNext()) { Map.Entry pair = it.next(); params.put(pair.getKey(), pair.getValue()); it.remove(); } } StringBuilder postData = new StringBuilder(); for (Map.Entry param : params.entrySet()) { if (postData.length() != 0) postData.append('&'); postData.append(param.getKey()); postData.append('='); postData.append(param.getValue()); } byte[] postDataBytes = postData.toString().getBytes(StandardCharsets.UTF_8); if (proxy != null) httpURLConnection = (HttpsURLConnection) url.openConnection(proxy); else httpURLConnection = (HttpsURLConnection) url.openConnection(); httpURLConnection.setRequestProperty("User-Agent", USER_AGENT); if (httpURLConnection instanceof HttpsURLConnection) { ((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(new TLSSocketFactory(this.instance)); } setToken(token); httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); httpURLConnection.setRequestMethod("DELETE"); httpURLConnection.setConnectTimeout(timeout * 1000); httpURLConnection.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length)); httpURLConnection.getOutputStream().write(postDataBytes); if (httpURLConnection.getResponseCode() >= 200 && httpURLConnection.getResponseCode() < 400) { getSinceMaxId(); httpURLConnection.getInputStream().close(); return httpURLConnection.getResponseCode(); } else { String error = null; if (httpURLConnection.getErrorStream() != null) { InputStream stream = httpURLConnection.getErrorStream(); if (stream == null) { stream = httpURLConnection.getInputStream(); } try (Scanner scanner = new Scanner(stream)) { scanner.useDelimiter("\\Z"); if (scanner.hasNext()) { error = scanner.next(); } } catch (Exception e) { e.printStackTrace(); } } int responseCode = httpURLConnection.getResponseCode(); try { httpURLConnection.getInputStream().close(); } catch (Exception ignored) { } throw new HttpsConnectionException(responseCode, error); } } public String getSince_id() { return since_id; } public String getMax_id() { return max_id; } private void getSinceMaxId() { if (Helper.getLiveInstanceWithProtocol(context) == null) return; if (httpURLConnection == null) return; Map> map = httpURLConnection.getHeaderFields(); if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { for (Map.Entry> entry : map.entrySet()) { if (entry.toString().startsWith("Link") || entry.toString().startsWith("link")) { Pattern patternMaxId = Pattern.compile("max_id=([0-9a-zA-Z]+).*"); Matcher matcherMaxId = patternMaxId.matcher(entry.toString()); if (matcherMaxId.find()) { max_id = matcherMaxId.group(1); } if (entry.toString().startsWith("Link")) { Pattern patternSinceId = Pattern.compile("since_id=([0-9a-zA-Z]+).*"); Matcher matcherSinceId = patternSinceId.matcher(entry.toString()); if (matcherSinceId.find()) { since_id = matcherSinceId.group(1); } } } else if (entry.toString().startsWith("Min-Id") || entry.toString().startsWith("min-id")) { Pattern patternMaxId = Pattern.compile("min-id=\\[([0-9a-zA-Z]+).*]"); Matcher matcherMaxId = patternMaxId.matcher(entry.toString()); if (matcherMaxId.find()) { max_id = matcherMaxId.group(1); } } } } } private String converToString(InputStream inputStream) { java.util.Scanner s = new java.util.Scanner(inputStream).useDelimiter("\\A"); return s.hasNext() ? s.next() : ""; } int getActionCode() { try { return httpURLConnection.getResponseCode(); } catch (IOException e) { return -1; } } public class HttpsConnectionException extends Exception { private final int statusCode; private final String message; HttpsConnectionException(int statusCode, String message) { this.statusCode = statusCode; SpannableString spannableString; if (message != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) spannableString = new SpannableString(Html.fromHtml(message, Html.FROM_HTML_MODE_LEGACY)); else spannableString = new SpannableString(Html.fromHtml(message)); } else { spannableString = new SpannableString(context.getString(R.string.toast_error)); } this.message = spannableString.toString(); } public int getStatusCode() { return statusCode; } @Override public String getMessage() { return message; } } }