implemented provisioning routine

This commit is contained in:
Michael Pöhn 2018-01-24 16:20:38 +01:00
parent bb1292586b
commit aab46c8ab2

View File

@ -3,12 +3,14 @@ package org.fdroid.fdroid;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Environment;
import android.util.Base64; import android.util.Base64;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.fdroid.fdroid.data.Repo;
import org.fdroid.fdroid.data.RepoProvider;
import org.fdroid.fdroid.views.ManageReposActivity;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -26,11 +28,18 @@ import java.util.zip.ZipInputStream;
/** /**
* @author Michael Pöhn (michael.poehn@fsfe.org) * @author Michael Pöhn (michael.poehn@fsfe.org)
*/ */
@SuppressWarnings("LineLength")
public class Provisioner { public class Provisioner {
public static final String TAG = "Provisioner"; public static final String TAG = "Provisioner";
private static final String DEFAULT_PROVISION_DIR = Environment.getExternalStorageDirectory().getPath(); /**
* This is the name of the subfolder in the file directory of this app
* where {@link Provisioner} looks for new provisions.
*
* eg. in the Emulator (API level 24): /data/user/0/org.fdroid.fdroid.debug/files/provisions
*/
private static final String NEW_PROVISIONS_DIR = "provisions";
protected Provisioner() { protected Provisioner() {
} }
@ -38,39 +47,74 @@ public class Provisioner {
/** /**
* search for provision files and process them * search for provision files and process them
*/ */
public void scanAndProcess(Context context) { public static void scanAndProcess(Context context) {
List<File> files = findProvisionFiles(); File provisionDir = new File(context.getExternalFilesDir(null).getAbsolutePath() + File.separator + NEW_PROVISIONS_DIR);
List<ProvisionPlaintext> plaintexts = extractProvisionsPlaintext(files);
files.clear();
List<Provision> provisions = parseProvisions(plaintexts); if (!provisionDir.isDirectory()) {
plaintexts.clear(); Utils.debugLog(TAG, "Provisions dir does not exists: '" + provisionDir.getAbsolutePath() + "' moving on ...");
} else if (provisionDir.list().length == 0) {
Utils.debugLog(TAG, "Provisions dir is empty: '" + provisionDir.getAbsolutePath() + "' moving on ...");
} else {
// TODO: do something useful with provisions, like prompting users Provisioner p = new Provisioner();
List<File> files = p.findProvisionFiles(context);
List<ProvisionPlaintext> plaintexts = p.extractProvisionsPlaintext(files);
List<Provision> provisions = p.parseProvisions(plaintexts);
if (provisions == null || provisions.size() == 0) {
Utils.debugLog(TAG, "Provision dir does not contain any provisions: '" + provisionDir.getAbsolutePath() + "' moving on ...");
} else {
int cleanupCounter = 0;
for (Provision provision : provisions) { for (Provision provision : provisions) {
if (provision.getRepositoryProvision() != null) { if (provision.getRepositoryProvision() != null) {
RepositoryProvision repo = provision.getRepositoryProvision(); RepositoryProvision repo = provision.getRepositoryProvision();
Utils.debugLog(TAG, "repository:"
+ " " + repo.getName()
+ " " + repo.getUrl()
+ " " + repo.getUsername());
Intent i = new Intent(Intent.ACTION_VIEW); // TODO uniqx: check if repo is already enable
i.setData(Uri.parse(repo.getUrl())); Repo storedRepo = RepoProvider.Helper.findByAddress(context, repo.getUrl());
if (storedRepo != null) {
Utils.debugLog(TAG, "Provision contains a repo which is already added: '" + provision.getProvisonPath() + "' ignoring ...");
} else {
// Note: only the last started activity will visible to users.
// All other prompting attempts will be lost.
Uri origUrl = Uri.parse(repo.getUrl());
Uri.Builder data = new Uri.Builder();
data.scheme(origUrl.getScheme());
data.encodedAuthority(Uri.encode(repo.getUsername()) + ":" + Uri.encode(repo.getPassword()) + "@" + Uri.encode(origUrl.getAuthority()));
data.path(origUrl.getPath());
data.appendQueryParameter("fingerprint", repo.getSigfp());
Intent i = new Intent(context, ManageReposActivity.class);
i.setData(data.build());
context.startActivity(i); context.startActivity(i);
Utils.debugLog(TAG, "Provision processed: '" + provision.getProvisonPath() + "' prompted user ...");
}
}
// remove provision file
try {
new File(provision.getProvisonPath()).delete();
cleanupCounter++;
} catch (SecurityException e) {
// ignore this exception
Utils.debugLog(TAG, "Removing provision not possible: " + e.getMessage() + " ()");
}
}
Utils.debugLog(TAG, "Provisions done, removed " + cleanupCounter + " provision(s).");
} }
} }
} }
/** public List<File> findProvisionFiles(Context context) {
* @return List of String provisionDirPath = context.getExternalFilesDir(null).getAbsolutePath() + File.separator + NEW_PROVISIONS_DIR;
*/ return findProvisionFilesInDir(new File(provisionDirPath));
public List<File> findProvisionFiles() {
return findProvisionFilesInDir(new File(DEFAULT_PROVISION_DIR));
} }
protected List<File> findProvisionFilesInDir(File file) { protected List<File> findProvisionFilesInDir(File file) {
if (file == null || !file.isDirectory()) {
return new ArrayList<>();
}
try {
File[] files = file.listFiles(new FilenameFilter() { File[] files = file.listFiles(new FilenameFilter() {
@Override @Override
public boolean accept(File dir, String name) { public boolean accept(File dir, String name) {
@ -81,6 +125,10 @@ public class Provisioner {
} }
}); });
return files != null ? Arrays.asList(files) : null; return files != null ? Arrays.asList(files) : null;
} catch (Exception e) {
Utils.debugLog(TAG, "can not search for provisions, can not access: " + file.getAbsolutePath(), e);
return new ArrayList<>();
}
} }
String rot13(String text) { String rot13(String text) {
@ -109,6 +157,7 @@ public class Provisioner {
protected List<ProvisionPlaintext> extractProvisionsPlaintext(List<File> files) { protected List<ProvisionPlaintext> extractProvisionsPlaintext(List<File> files) {
List<ProvisionPlaintext> result = new ArrayList<>(); List<ProvisionPlaintext> result = new ArrayList<>();
if (files != null) {
for (File file : files) { for (File file : files) {
ProvisionPlaintext plain = new ProvisionPlaintext(); ProvisionPlaintext plain = new ProvisionPlaintext();
plain.setProvisionPath(file.getAbsolutePath()); plain.setProvisionPath(file.getAbsolutePath());
@ -142,6 +191,7 @@ public class Provisioner {
result.add(plain); result.add(plain);
} }
}
return result; return result;
} }
@ -150,16 +200,18 @@ public class Provisioner {
List<Provision> provisions = new ArrayList<>(); List<Provision> provisions = new ArrayList<>();
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
if (provisionPlaintexts != null) {
for (ProvisionPlaintext provisionPlaintext : provisionPlaintexts) { for (ProvisionPlaintext provisionPlaintext : provisionPlaintexts) {
Provision provision = new Provision(); Provision provision = new Provision();
provision.setProvisonPath(provisionPlaintext.getProvisionPath()); provision.setProvisonPath(provisionPlaintext.getProvisionPath());
try { try {
provision.setRepositoryProvision( provision.setRepositoryProvision(
mapper.readValue(provisionPlaintext.getRepositoryProvision(), RepositoryProvision.class)); mapper.readValue(provisionPlaintext.getRepositoryProvision(), RepositoryProvision.class));
provisions.add(provision);
} catch (IOException e) { } catch (IOException e) {
Utils.debugLog(TAG, "could not parse repository provision", e); Utils.debugLog(TAG, "could not parse repository provision", e);
} }
provisions.add(provision); }
} }
return provisions; return provisions;