460 lines
16 KiB
Java
460 lines
16 KiB
Java
package com.localtransfer;
|
|
|
|
import android.animation.ObjectAnimator;
|
|
import android.app.Activity;
|
|
import android.content.Context;
|
|
import android.content.SharedPreferences;
|
|
import android.database.Cursor;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.net.Uri;
|
|
import android.os.Parcel;
|
|
import android.os.Parcelable;
|
|
import android.provider.OpenableColumns;
|
|
import android.util.Log;
|
|
import android.view.View;
|
|
import android.view.animation.Animation;
|
|
import android.view.animation.LinearInterpolator;
|
|
import android.widget.Button;
|
|
import android.widget.LinearLayout;
|
|
import android.widget.TextView;
|
|
|
|
import androidx.core.app.NotificationCompat;
|
|
import androidx.core.app.NotificationManagerCompat;
|
|
import androidx.core.content.FileProvider;
|
|
import androidx.preference.PreferenceManager;
|
|
|
|
import com.google.android.material.snackbar.Snackbar;
|
|
|
|
import java.io.DataOutputStream;
|
|
import java.io.File;
|
|
import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.InputStreamReader;
|
|
import java.io.OutputStreamWriter;
|
|
import java.io.Serializable;
|
|
import java.net.HttpURLConnection;
|
|
import java.net.ProtocolException;
|
|
import java.net.URL;
|
|
import java.net.URLEncoder;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.text.CharacterIterator;
|
|
import java.text.SimpleDateFormat;
|
|
import java.text.StringCharacterIterator;
|
|
import java.util.ConcurrentModificationException;
|
|
import java.util.Date;
|
|
import java.util.List;
|
|
import java.util.Timer;
|
|
import java.util.TimerTask;
|
|
|
|
import static java.lang.Integer.valueOf;
|
|
|
|
public class Transfer {
|
|
|
|
public static String host;
|
|
public static Integer port;
|
|
public static String root;
|
|
public static String protocol;
|
|
public static String local_storage;
|
|
|
|
public static Activity activity;
|
|
|
|
public static void parameter(Context context) {
|
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
|
|
|
host = prefs.getString("host", null);
|
|
port = valueOf(prefs.getString("port", null));
|
|
root = prefs.getString("root", null);
|
|
local_storage = prefs.getString("local_storage", null);
|
|
if(prefs.getBoolean("protocol", false))
|
|
protocol = "https";
|
|
else
|
|
protocol = "http";
|
|
}
|
|
|
|
private URL checkRedirection(URL url) throws IOException {
|
|
String location = null;
|
|
HttpURLConnection conn = null;
|
|
int responseCode;
|
|
int nbRedirect = 0;
|
|
|
|
do {
|
|
|
|
conn = (HttpURLConnection) url.openConnection();
|
|
conn.setRequestMethod("GET");
|
|
conn.setInstanceFollowRedirects(false);
|
|
conn.setConnectTimeout(2000);
|
|
|
|
conn.connect();
|
|
responseCode = conn.getResponseCode();
|
|
|
|
Log.d("Réponse Code", String.valueOf(responseCode));
|
|
|
|
if(responseCode != HttpURLConnection.HTTP_MOVED_PERM && responseCode != HttpURLConnection.HTTP_MOVED_TEMP) {
|
|
break;
|
|
}
|
|
|
|
location = conn.getHeaderField("Location");
|
|
Log.d("Location", location);
|
|
|
|
url = new URL(location);
|
|
|
|
|
|
conn.disconnect();
|
|
|
|
nbRedirect++;
|
|
if(nbRedirect > 10) {
|
|
throw new ProtocolException("Too many follow-up requests: " + nbRedirect);
|
|
}
|
|
|
|
|
|
} while (responseCode == HttpURLConnection.HTTP_MOVED_PERM || responseCode == HttpURLConnection.HTTP_MOVED_TEMP);
|
|
|
|
return url;
|
|
}
|
|
|
|
public void handleSendFile(Uri uri) {
|
|
if (uri != null) {
|
|
new Thread(() -> {
|
|
try {
|
|
uploadFile(uri);
|
|
} catch (IOException e) {
|
|
final String ExceptionName = e.getClass().getSimpleName();
|
|
final String ExceptionMess = e.getMessage();
|
|
|
|
if(ExceptionName != null && ExceptionMess != null) {
|
|
Transfer.error(ExceptionName + ": " + ExceptionMess, null, null);
|
|
}
|
|
|
|
}
|
|
}).start();
|
|
}
|
|
}
|
|
|
|
public void handleSendText(String sharedText) {
|
|
if (sharedText != null) {
|
|
SimpleDateFormat sdfDate = new SimpleDateFormat("yyyyMMdd_HHmmss");
|
|
Date now = new Date();
|
|
String strDate = sdfDate.format(now);
|
|
new Thread(() -> {
|
|
try {
|
|
File outputFile = new File(activity.getCacheDir(), strDate + ".txt");
|
|
FileOutputStream fileOut = new FileOutputStream(outputFile);
|
|
OutputStreamWriter OutWriter = new OutputStreamWriter(fileOut);
|
|
OutWriter.append(sharedText);
|
|
OutWriter.close();
|
|
|
|
fileOut.flush();
|
|
fileOut.close();
|
|
|
|
Uri uri = FileProvider.getUriForFile(activity, activity.getPackageName(), outputFile);
|
|
|
|
uploadFile(uri);
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}).start();
|
|
}
|
|
}
|
|
|
|
public String uploadFile(Uri uri) throws IOException {
|
|
String message = null;
|
|
URL url = null;
|
|
HttpURLConnection conn = null;
|
|
DataOutputStream request = null;
|
|
String boundary = "*****";
|
|
int maxBufferSize = 1 * 1024 * 1024;
|
|
byte[] buffer = new byte[maxBufferSize];
|
|
int bufferLength;
|
|
long loaded = 0;
|
|
|
|
Cursor cursor = activity.getContentResolver().query(uri, null, null, null, null);
|
|
cursor.moveToFirst();
|
|
String fileName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
|
|
String fileNameUTF8 = new String(fileName.getBytes(), StandardCharsets.ISO_8859_1);
|
|
long fileSize = cursor.getLong(cursor.getColumnIndex(OpenableColumns.SIZE));
|
|
String type = activity.getContentResolver().getType(uri);
|
|
|
|
url = new URL(protocol, host, port, root + "/upload.php");
|
|
|
|
url = checkRedirection(url);
|
|
|
|
Progress p = new Progress(fileName, fileSize, Progress.UPLOAD);
|
|
|
|
if(url != null) {
|
|
|
|
Log.d("URL", url.toString());
|
|
|
|
conn = (HttpURLConnection) url.openConnection();
|
|
conn.setDoInput(true); // Allow Inputs
|
|
conn.setDoOutput(true); // Allow Outputs
|
|
conn.setUseCaches(false); // Don't use a Cached Copy
|
|
conn.setChunkedStreamingMode(maxBufferSize);
|
|
conn.setRequestMethod("POST");
|
|
conn.setRequestProperty("Connection", "keep-alive");
|
|
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
|
|
|
|
conn.connect();
|
|
|
|
request = new DataOutputStream(conn.getOutputStream());
|
|
|
|
request.writeBytes("--" + boundary + "\r\n");
|
|
request.writeBytes("Content-Disposition: form-data; name=\"file\"; filename=\"" + fileNameUTF8 + "\"\r\n");
|
|
request.writeBytes("Content-Type: " + type + "\r\n\r\n");
|
|
|
|
InputStream in = activity.getContentResolver().openInputStream(uri);
|
|
|
|
while ((bufferLength = in.read(buffer)) > 0) {
|
|
request.write(buffer, 0, bufferLength);
|
|
loaded+= (long) bufferLength;
|
|
p.loaded = loaded;
|
|
p.percent = ((loaded * 100) / fileSize);
|
|
}
|
|
|
|
request.writeBytes("\r\n");
|
|
request.writeBytes("--" + boundary + "--\r\n");
|
|
|
|
in.close();
|
|
|
|
int responseCode = conn.getResponseCode();
|
|
|
|
if (responseCode == HttpURLConnection.HTTP_OK) {
|
|
message = "File " + fileName + " successful upload";
|
|
p.stopProgress();
|
|
}
|
|
else {
|
|
String s = conn.getResponseMessage();
|
|
throw new HttpErrorException("error code: " + responseCode + " " + s);
|
|
}
|
|
|
|
request.flush();
|
|
|
|
request.close();
|
|
|
|
conn.disconnect();
|
|
|
|
System.out.println(message);
|
|
if (activity != null) {
|
|
String finalMessage = message;
|
|
activity.runOnUiThread(() ->
|
|
Snackbar.make(activity.findViewById(R.id.view_pager), finalMessage, Snackbar.LENGTH_LONG)
|
|
.setAction("Action", null).show());
|
|
}
|
|
}
|
|
|
|
return message;
|
|
}
|
|
|
|
public String getFileList() throws IOException {
|
|
URL url = null;
|
|
HttpURLConnection conn = null;
|
|
|
|
String fileList = "";
|
|
int buf;
|
|
|
|
url = new URL(protocol, host, port, root + "/list.php");
|
|
conn = (HttpURLConnection) url.openConnection();
|
|
conn.setConnectTimeout(2000);
|
|
|
|
conn.connect();
|
|
|
|
int responseCode = conn.getResponseCode();
|
|
|
|
if (responseCode == HttpURLConnection.HTTP_OK) {
|
|
InputStreamReader isw = new InputStreamReader(conn.getInputStream());
|
|
|
|
while ((buf = isw.read()) > 0) {
|
|
fileList = fileList + (char) buf;
|
|
}
|
|
}
|
|
else {
|
|
String s = conn.getResponseMessage();
|
|
throw new HttpErrorException("error code: " + responseCode + " " + s);
|
|
}
|
|
|
|
conn.disconnect();
|
|
|
|
return fileList;
|
|
}
|
|
|
|
public void downloadFile(final File file, String name, long fileSize, String href, Button button) throws IOException {
|
|
|
|
/*final LinearLayout layout = activity.findViewById(id);
|
|
final Button button;
|
|
if(layout != null)
|
|
button = layout.findViewById(R.id.file_download);
|
|
else
|
|
button = null;*/
|
|
|
|
URL url = null;
|
|
HttpURLConnection conn = null;
|
|
int maxBufferSize = 1 * 1024 * 1024;
|
|
byte[] buffer = new byte[maxBufferSize];
|
|
int bufferLength;
|
|
long loaded = 0;
|
|
|
|
final Drawable image = activity.getDrawable(R.drawable.ic_spinner_rotate);
|
|
|
|
Progress p = new Progress(name, fileSize, Progress.DOWNLOAD);
|
|
if(button != null)
|
|
p.button = button;
|
|
|
|
if(p.button != null) {
|
|
activity.runOnUiThread(() -> {
|
|
int h = image.getIntrinsicHeight();
|
|
int w = image.getIntrinsicWidth();
|
|
image.setBounds(0, 0, w, h);
|
|
p.button.setCompoundDrawables(button.getCompoundDrawables()[0], null, image, null);
|
|
ObjectAnimator anim = ObjectAnimator.ofInt(image, "level", 0, 10000);
|
|
anim.setDuration(1000);
|
|
anim.setRepeatCount(Animation.INFINITE);
|
|
anim.setInterpolator(new LinearInterpolator());
|
|
anim.start();
|
|
});
|
|
}
|
|
|
|
String[] parts = href.split("/");
|
|
String path = "";
|
|
for(int i=0; i< parts.length - 1; i++) {
|
|
path = path + parts[i] + "/";
|
|
}
|
|
String query = URLEncoder.encode(parts[parts.length - 1], StandardCharsets.UTF_8.toString());
|
|
url = new URL(protocol, host, port, path + query.replace("+", "%20"));
|
|
conn = (HttpURLConnection) url.openConnection();
|
|
conn.setDoOutput(true);
|
|
conn.setRequestMethod("GET");
|
|
conn.setConnectTimeout(2000);
|
|
|
|
Log.d("URL", url.toString());
|
|
|
|
conn.connect();
|
|
|
|
int responseCode = conn.getResponseCode();
|
|
|
|
if (responseCode == HttpURLConnection.HTTP_OK) {
|
|
|
|
FileOutputStream fileOutput = new FileOutputStream(file);
|
|
InputStream in = conn.getInputStream();
|
|
|
|
while ((bufferLength = in.read(buffer)) > 0) {
|
|
fileOutput.write(buffer, 0, bufferLength);
|
|
loaded+= (long) bufferLength;
|
|
p.loaded = loaded;
|
|
p.percent = ((loaded * 100) / fileSize);
|
|
if(Progress.app_started && p.button != null)
|
|
activity.runOnUiThread(() -> p.button.setText(String.format("Download in progress %d%%", p.percent)));
|
|
}
|
|
fileOutput.close();
|
|
|
|
conn.disconnect();
|
|
|
|
p.stopProgress();
|
|
|
|
if(p.button != null) {
|
|
activity.runOnUiThread(() -> {
|
|
final LinearLayout layout = (LinearLayout) p.button.getParent();
|
|
layout.findViewById(R.id.file_view).setVisibility(LinearLayout.VISIBLE);
|
|
layout.findViewById(R.id.file_share).setVisibility(LinearLayout.VISIBLE);
|
|
p.button.setVisibility(LinearLayout.GONE);
|
|
p.button.setEnabled(true);
|
|
|
|
p.button.setText(activity.getString(R.string.file_download));
|
|
p.button.setCompoundDrawables(p.button.getCompoundDrawables()[0], null, null, null);
|
|
});
|
|
}
|
|
activity.runOnUiThread(() -> {
|
|
String message = "File " + name + " successful download";
|
|
System.out.println(message);
|
|
Snackbar.make(activity.findViewById(R.id.view_pager), message, Snackbar.LENGTH_LONG)
|
|
.setAction("Action", null).show();
|
|
});
|
|
}
|
|
else {
|
|
String s = conn.getResponseMessage();
|
|
throw new HttpErrorException("error code: " + responseCode + " " + s);
|
|
}
|
|
|
|
conn.disconnect();
|
|
}
|
|
|
|
public String deleteFile(String file) throws IOException {
|
|
|
|
URL url = null;
|
|
HttpURLConnection conn = null;
|
|
|
|
String message;
|
|
|
|
String query = URLEncoder.encode(file, StandardCharsets.UTF_8.toString());
|
|
String serverUrl = root + "/delete.php?file=" + query;
|
|
url = new URL(protocol, host, port, serverUrl);
|
|
conn = (HttpURLConnection) url.openConnection();
|
|
conn.setRequestMethod("GET");
|
|
conn.setConnectTimeout(2000);
|
|
|
|
conn.connect();
|
|
|
|
int responseCode = conn.getResponseCode();
|
|
|
|
if (responseCode == HttpURLConnection.HTTP_OK) {
|
|
|
|
message = "File " + file + " successful deleted";
|
|
}
|
|
else {
|
|
String s = conn.getResponseMessage();
|
|
throw new HttpErrorException("error code: " + responseCode + " " + s);
|
|
}
|
|
|
|
conn.disconnect();
|
|
|
|
return message;
|
|
}
|
|
|
|
private static int timeout;
|
|
|
|
public static void error(final String message, final TextView title, final LinearLayout layout) {
|
|
|
|
System.out.println(message);
|
|
|
|
if (timeout == 0) {
|
|
if (activity != null) {
|
|
activity.runOnUiThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
if(layout != null)
|
|
layout.removeAllViews();
|
|
if(title != null) {
|
|
layout.addView(title);
|
|
title.setText(message);
|
|
}
|
|
Snackbar.make(activity.findViewById(R.id.view_pager), message, Snackbar.LENGTH_LONG)
|
|
.setAction("Action", null).show();
|
|
}
|
|
});
|
|
}
|
|
timeout = 1;
|
|
new Timer().schedule(new TimerTask() {
|
|
@Override
|
|
public void run() {
|
|
timeout = 0;
|
|
}
|
|
}, 3000);
|
|
}
|
|
}
|
|
|
|
public static String humanReadableByteCountBin(long bytes) {
|
|
long absB = bytes == Long.MIN_VALUE ? Long.MAX_VALUE : Math.abs(bytes);
|
|
if (absB < 1024) {
|
|
return bytes + " B";
|
|
}
|
|
long value = absB;
|
|
CharacterIterator ci = new StringCharacterIterator("KMGTPE");
|
|
for (int i = 40; i >= 0 && absB > 0xfffccccccccccccL >> i; i -= 10) {
|
|
value >>= 10;
|
|
ci.next();
|
|
}
|
|
value *= Long.signum(bytes);
|
|
return String.format("%.1f %ciB", value / 1024.0, ci.current());
|
|
}
|
|
}
|
|
|