|
|
@@ -1,39 +1,32 @@
|
|
|
package info.knacki.pass.git;
|
|
|
|
|
|
-import android.os.AsyncTask;
|
|
|
-import android.util.Base64;
|
|
|
-
|
|
|
import java.io.IOException;
|
|
|
-import java.io.InputStream;
|
|
|
import java.io.OutputStream;
|
|
|
-import java.net.Authenticator;
|
|
|
-import java.net.HttpURLConnection;
|
|
|
import java.net.MalformedURLException;
|
|
|
-import java.net.PasswordAuthentication;
|
|
|
import java.net.URL;
|
|
|
-import java.net.URLConnection;
|
|
|
import java.nio.ByteBuffer;
|
|
|
import java.nio.charset.Charset;
|
|
|
-import java.util.ArrayList;
|
|
|
import java.util.HashMap;
|
|
|
-import java.util.List;
|
|
|
import java.util.Locale;
|
|
|
-import java.util.Map;
|
|
|
import java.util.SortedSet;
|
|
|
import java.util.logging.Level;
|
|
|
import java.util.logging.Logger;
|
|
|
-import java.util.zip.InflaterInputStream;
|
|
|
|
|
|
import info.knacki.pass.git.entities.GitCommit;
|
|
|
import info.knacki.pass.git.entities.GitObject;
|
|
|
import info.knacki.pass.git.entities.GitPackable;
|
|
|
import info.knacki.pass.git.entities.GitPackableUtil;
|
|
|
import info.knacki.pass.git.entities.GitRef;
|
|
|
+import info.knacki.pass.io.CharsetHelper;
|
|
|
import info.knacki.pass.io.OnResponseListener;
|
|
|
import info.knacki.pass.io.OnStreamResponseListener;
|
|
|
import info.knacki.pass.io.OutputStreamWithCheckSum;
|
|
|
import info.knacki.pass.settings.SettingsManager;
|
|
|
|
|
|
+import static info.knacki.pass.io.NetworkUtils.ProtoPost;
|
|
|
+import static info.knacki.pass.io.NetworkUtils.protoGet;
|
|
|
+import static info.knacki.pass.io.NetworkUtils.protoInflateGet;
|
|
|
+
|
|
|
class HttpGitProtocol implements GitInterface {
|
|
|
private final SettingsManager.Git fConfig;
|
|
|
private GitRef[] fRefsCache = null;
|
|
|
@@ -43,222 +36,6 @@ class HttpGitProtocol implements GitInterface {
|
|
|
fConfig = config;
|
|
|
}
|
|
|
|
|
|
- static class DownloaderTask extends AsyncTask<Void, Void, Integer> {
|
|
|
- private final URL fUrl;
|
|
|
- private OnResponseListener<byte[]> fResp;
|
|
|
- private final SettingsManager.Git fConfig;
|
|
|
-
|
|
|
- DownloaderTask(URL url, SettingsManager.Git config, OnResponseListener<byte[]> resp) {
|
|
|
- fUrl = url;
|
|
|
- fResp = resp;
|
|
|
- fConfig = config;
|
|
|
- }
|
|
|
-
|
|
|
- DownloaderTask(URL url, SettingsManager.Git config) {
|
|
|
- fUrl = url;
|
|
|
- fConfig = config;
|
|
|
- }
|
|
|
-
|
|
|
- void SetResultHandler(OnResponseListener<byte[]> handler) {
|
|
|
- fResp = handler;
|
|
|
- }
|
|
|
-
|
|
|
- protected InputStream GetInputFilter(URLConnection in) throws IOException {
|
|
|
- return in.getInputStream();
|
|
|
- }
|
|
|
-
|
|
|
- protected void ManageResponse(byte[] resp) {
|
|
|
- fResp.OnResponse(resp);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- protected Integer doInBackground(Void... voids) {
|
|
|
- try {
|
|
|
- log.log(Level.INFO, "fetching " +fUrl.toString());
|
|
|
- URLConnection httpClient = fUrl.openConnection();
|
|
|
- if (fConfig.HasAuthentication()) {
|
|
|
- Authenticator.setDefault(new Authenticator() {
|
|
|
- @Override
|
|
|
- protected PasswordAuthentication getPasswordAuthentication() {
|
|
|
- return new PasswordAuthentication(fConfig.GetUser(), fConfig.GetPassword().toCharArray());
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- InputStream in = GetInputFilter(httpClient);
|
|
|
- ArrayList<byte[]> fullBuffer = new ArrayList<>();
|
|
|
- int totalRead = 0;
|
|
|
- byte[] buffer = new byte[1024];
|
|
|
- int currentRead;
|
|
|
- while ((currentRead = in.read(buffer, 0, 1024)) != 0) {
|
|
|
- fullBuffer.add(buffer);
|
|
|
- buffer = new byte[1024];
|
|
|
- totalRead += currentRead;
|
|
|
- if (currentRead < 1024)
|
|
|
- break;
|
|
|
- }
|
|
|
- in.close();
|
|
|
- buffer = new byte[totalRead];
|
|
|
- int i =0;
|
|
|
- for (byte []currentBuf: fullBuffer) {
|
|
|
- for (int j =0; j < currentBuf.length && i*1024+j < totalRead; ++j) {
|
|
|
- buffer[i*1024 +j] = currentBuf[j];
|
|
|
- }
|
|
|
- ++i;
|
|
|
- }
|
|
|
- ManageResponse(buffer);
|
|
|
- }
|
|
|
- catch (IOException e) {
|
|
|
- log.log(Level.WARNING, e.getMessage(), e);
|
|
|
- fResp.OnError(e.getClass().getSimpleName() +": " +e.getMessage(), e);
|
|
|
- }
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- static class PostTask extends AsyncTask<Void, Void, Integer> {
|
|
|
- private final URL fUrl;
|
|
|
- private final OnResponseListener<byte[]> fResp;
|
|
|
- private final SettingsManager.Git fConfig;
|
|
|
- private final OnResponseListener<OutputStream> fOnReadyWrite;
|
|
|
- private final Map<String, String> fHeaders;
|
|
|
-
|
|
|
- PostTask(URL url, SettingsManager.Git config, Map<String, String> headers, OnResponseListener<byte[]> resp, OnResponseListener<OutputStream> onReadyWrite) {
|
|
|
- fUrl = url;
|
|
|
- fResp = resp;
|
|
|
- fConfig = config;
|
|
|
- fOnReadyWrite = onReadyWrite;
|
|
|
- fHeaders = headers;
|
|
|
- }
|
|
|
-
|
|
|
- protected InputStream GetInputFilter(URLConnection in) throws IOException {
|
|
|
- try {
|
|
|
- return in.getInputStream();
|
|
|
- } catch (Throwable e) {
|
|
|
- Map<String, List<String>> headers = in.getHeaderFields();
|
|
|
- String msg = null;
|
|
|
- if (!headers.values().isEmpty()) {
|
|
|
- List<String> statuses = headers.values().iterator().next();
|
|
|
- if (!statuses.isEmpty())
|
|
|
- msg = in.getURL().toString() + ": " +statuses.iterator().next();
|
|
|
- }
|
|
|
- if (msg == null)
|
|
|
- msg = "Tried to reach " +in.getURL().toString();
|
|
|
- log.log(Level.SEVERE, msg, e);
|
|
|
- throw e;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- protected void ManageResponse(byte[] resp) {
|
|
|
- fResp.OnResponse(resp);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- protected Integer doInBackground(Void... voids) {
|
|
|
- try {
|
|
|
- log.log(Level.INFO, "fetching " +fUrl.toString());
|
|
|
- HttpURLConnection httpClient = (HttpURLConnection) fUrl.openConnection();
|
|
|
- httpClient.setRequestMethod("POST");
|
|
|
- for (Map.Entry<String, String> header: fHeaders.entrySet()) {
|
|
|
- httpClient.setRequestProperty(header.getKey(), header.getValue());
|
|
|
- }
|
|
|
- if (fConfig.HasAuthentication()) {
|
|
|
- httpClient.setRequestProperty("Authorization", "basic " +Base64.encodeToString("fConfig.GetUser():fConfig.GetPassword()".getBytes(), Base64.NO_WRAP));
|
|
|
- }
|
|
|
- fOnReadyWrite.OnResponse(httpClient.getOutputStream());
|
|
|
- InputStream in = GetInputFilter(httpClient);
|
|
|
- ArrayList<byte[]> fullBuffer = new ArrayList<>();
|
|
|
- int totalRead = 0;
|
|
|
- byte[] buffer = new byte[1024];
|
|
|
- int currentRead;
|
|
|
- while ((currentRead = in.read(buffer, 0, 1024)) > 0) {
|
|
|
- fullBuffer.add(buffer);
|
|
|
- buffer = new byte[1024];
|
|
|
- totalRead += currentRead;
|
|
|
- if (currentRead < 1024)
|
|
|
- break;
|
|
|
- }
|
|
|
- in.close();
|
|
|
- if (totalRead >= 0) {
|
|
|
- buffer = new byte[totalRead];
|
|
|
- int i = 0;
|
|
|
- for (byte[] currentBuf : fullBuffer) {
|
|
|
- for (int j = 0; j < currentBuf.length && i * 1024 + j < totalRead; ++j) {
|
|
|
- buffer[i * 1024 + j] = currentBuf[j];
|
|
|
- }
|
|
|
- ++i;
|
|
|
- }
|
|
|
- ManageResponse(buffer);
|
|
|
- } else {
|
|
|
- ManageResponse(new byte[] {});
|
|
|
- }
|
|
|
- }
|
|
|
- catch (IOException e) {
|
|
|
- log.log(Level.WARNING, e.getMessage(), e);
|
|
|
- fResp.OnError(e.getClass().getSimpleName() +": " +e.getMessage(), e);
|
|
|
- }
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- static class DownloaderWithInflaterTask extends DownloaderTask {
|
|
|
- DownloaderWithInflaterTask(URL url, SettingsManager.Git config, OnResponseListener<byte[]> resp) {
|
|
|
- super(url, config, resp);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- protected InputStream GetInputFilter(URLConnection in) throws IOException {
|
|
|
- return new InflaterInputStream(super.GetInputFilter(in));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- protected void ManageResponse(byte[] result) {
|
|
|
- int i =0;
|
|
|
-
|
|
|
- while (i < result.length && result[i] != 0)
|
|
|
- ++i;
|
|
|
- if (i != result.length) {
|
|
|
- ++i;
|
|
|
- byte []arr = new byte[result.length -i];
|
|
|
- System.arraycopy(result, i, arr, 0, result.length -i);
|
|
|
- super.ManageResponse(arr);
|
|
|
- } else {
|
|
|
- super.ManageResponse(result);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- static class StringDownloaderTask extends DownloaderTask {
|
|
|
- private final OnResponseListener<String> onResp;
|
|
|
-
|
|
|
- StringDownloaderTask(URL url, SettingsManager.Git config, OnResponseListener<String> resultHandler) {
|
|
|
- super(url, config);
|
|
|
- SetResultHandler(new OnResponseListener<byte[]>() {
|
|
|
- @Override
|
|
|
- public void OnResponse(byte[] result) {
|
|
|
- StringDownloaderTask.this.onResp.OnResponse(new String(result, Charset.defaultCharset()));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void OnError(String msg, Throwable e) {
|
|
|
- StringDownloaderTask.this.onResp.OnError(msg, e);
|
|
|
- }
|
|
|
- });
|
|
|
- onResp = resultHandler;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private void protoInflateGet(final URL url, final OnResponseListener<byte[]> callback) {
|
|
|
- new DownloaderWithInflaterTask(url, fConfig, callback).execute();
|
|
|
- }
|
|
|
-
|
|
|
- private void ProtoPost(URL url, Map<String, String> headers, OnResponseListener<byte[]> callback, OnResponseListener<OutputStream> onReadyWrite) {
|
|
|
- new PostTask(url, fConfig, headers, callback, onReadyWrite).execute();
|
|
|
- }
|
|
|
-
|
|
|
- private void protoGet(final URL url, final OnResponseListener<String> callback) {
|
|
|
- new StringDownloaderTask(url, fConfig, callback).execute();
|
|
|
- }
|
|
|
-
|
|
|
public void GetRefs(final OnResponseListener<GitRef[]> callback) {
|
|
|
if (fRefsCache != null) {
|
|
|
callback.OnResponse(fRefsCache);
|
|
|
@@ -266,7 +43,7 @@ class HttpGitProtocol implements GitInterface {
|
|
|
}
|
|
|
try {
|
|
|
URL url = new URL(fConfig.GetUrl() + "/info/REFS");
|
|
|
- protoGet(url, new OnResponseListener<String>() {
|
|
|
+ protoGet(url, fConfig, new OnResponseListener<String>() {
|
|
|
@Override
|
|
|
public void OnResponse(String result) {
|
|
|
String [] refStrings = result.split("\n");
|
|
|
@@ -352,28 +129,26 @@ class HttpGitProtocol implements GitInterface {
|
|
|
while (i < data.length) {
|
|
|
byte[] mode = null;
|
|
|
int len;
|
|
|
- for (len =0; i +len <data.length && len < 8; ++len)
|
|
|
- if (data[i +len] == ' ') {
|
|
|
+ for (len =0; i +len <data.length && len < 8; ++len) {
|
|
|
+ if (data[i + len] == ' ') {
|
|
|
mode = new byte[len];
|
|
|
System.arraycopy(data, i, mode, 0, len);
|
|
|
- i += len +1;
|
|
|
+ i += len + 1;
|
|
|
break;
|
|
|
}
|
|
|
+ }
|
|
|
if (mode == null)
|
|
|
break;
|
|
|
- len = 0;
|
|
|
- while (i +len < data.length && data[i +len] != 0)
|
|
|
- ++len;
|
|
|
+ for (len =0; i +len < data.length && data[i +len] != 0; ++len);
|
|
|
byte[] filenameBytes = new byte[len];
|
|
|
System.arraycopy(data, i, filenameBytes, 0, len);
|
|
|
- String fileName = new String(filenameBytes, Charset.defaultCharset());
|
|
|
i += len +1;
|
|
|
if (i +20 > data.length)
|
|
|
break;
|
|
|
byte []sha1 = new byte[20];
|
|
|
System.arraycopy(data, i, sha1, 0, 20);
|
|
|
i += 20;
|
|
|
- tree.AddItem(GitObject.factory(tree, mode, fileName, sha1));
|
|
|
+ tree.AddItem(GitObject.factory(tree, mode, CharsetHelper.ByteArrayToString(filenameBytes), sha1));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -450,7 +225,7 @@ class HttpGitProtocol implements GitInterface {
|
|
|
response.OnError(e.getClass().getName() +": " +e.getMessage(), e);
|
|
|
return;
|
|
|
}
|
|
|
- protoInflateGet(url, response);
|
|
|
+ protoInflateGet(url, fConfig, response);
|
|
|
}
|
|
|
|
|
|
public boolean makePack(SortedSet<GitPackable> objectsToPack, OutputStream out) throws IOException
|
|
|
@@ -486,7 +261,7 @@ class HttpGitProtocol implements GitInterface {
|
|
|
try {
|
|
|
HashMap<String, String> headers = new HashMap<>();
|
|
|
headers.put("Content-Type", "application/x-git-receive-pack-request");
|
|
|
- ProtoPost(new URL(fConfig.GetUrl() +"/git-receive-pack"), headers, new OnResponseListener<byte[]>() {
|
|
|
+ ProtoPost(new URL(fConfig.GetUrl() +"/git-receive-pack"), headers, fConfig, new OnResponseListener<byte[]>() {
|
|
|
@Override
|
|
|
public void OnResponse(byte[] result) {
|
|
|
response.OnResponse(null);
|