From 0cf62450e017a031afc637841a34105c25279067 Mon Sep 17 00:00:00 2001 From: Arne Schwabe Date: Sat, 25 Jan 2014 14:57:40 +0100 Subject: Add the ability to select missing files from Convert Dialog --- .../blinkt/openvpn/activities/ConfigConverter.java | 321 ++++++++++++++------- src/de/blinkt/openvpn/core/NetworkSpace.java | 8 +- .../blinkt/openvpn/fragments/Settings_Basic.java | 8 +- src/de/blinkt/openvpn/fragments/Utils.java | 51 +++- src/de/blinkt/openvpn/views/FileSelectLayout.java | 40 ++- 5 files changed, 306 insertions(+), 122 deletions(-) (limited to 'src/de/blinkt/openvpn') diff --git a/src/de/blinkt/openvpn/activities/ConfigConverter.java b/src/de/blinkt/openvpn/activities/ConfigConverter.java index 491c79a9..2e24f94f 100644 --- a/src/de/blinkt/openvpn/activities/ConfigConverter.java +++ b/src/de/blinkt/openvpn/activities/ConfigConverter.java @@ -1,15 +1,8 @@ package de.blinkt.openvpn.activities; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.HashSet; -import java.util.List; -import java.util.Vector; +import java.io.*; +import java.util.*; import android.app.Activity; import android.app.AlertDialog; @@ -21,43 +14,39 @@ import android.os.Bundle; import android.os.Environment; import android.security.KeyChain; import android.security.KeyChainAliasCallback; -import android.text.TextUtils; import android.util.Base64; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; +import android.view.*; import android.widget.ArrayAdapter; import android.widget.CheckBox; +import android.widget.LinearLayout; import de.blinkt.openvpn.R; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ConfigParser; import de.blinkt.openvpn.core.ConfigParser.ConfigParseError; import de.blinkt.openvpn.core.ProfileManager; +import de.blinkt.openvpn.fragments.Utils; +import de.blinkt.openvpn.views.FileSelectLayout; +import junit.framework.Assert; -public class ConfigConverter extends ListActivity { +import static de.blinkt.openvpn.views.FileSelectLayout.*; + +public class ConfigConverter extends ListActivity implements FileSelectCallback { public static final String IMPORT_PROFILE = "de.blinkt.openvpn.IMPORT_PROFILE"; + private static final int RESULT_INSTALLPKCS12 = 7; + private static final int CHOOSE_FILE_OFFSET = 1000; + public static final String VPNPROFILE = "vpnProfile"; private VpnProfile mResult; - private ArrayAdapter mArrayAdapter; + private transient ArrayAdapter mArrayAdapter; - private List mPathsegments; + private transient List mPathsegments; private String mAliasName=null; - private int RESULT_INSTALLPKCS12 = 7; - - private String mPossibleName=null; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.config_converter); - } - + private Map fileSelectMap = new HashMap(); @Override public boolean onOptionsItemSelected(MenuItem item) { @@ -84,22 +73,76 @@ public class ConfigConverter extends ListActivity { } - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if(requestCode==RESULT_INSTALLPKCS12) { - if(resultCode==Activity.RESULT_OK) { - showCertDialog(); - } - } - - super.onActivityResult(requestCode, resultCode, data); - } + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + if(mResult!=null) + outState.putSerializable(VPNPROFILE,mResult); + outState.putString("mAliasName", mAliasName); + + String[] logentries = new String[mArrayAdapter.getCount()]; + for(int i =0; i < mArrayAdapter.getCount();i++){ + logentries[i] = mArrayAdapter.getItem(i); + } + outState.putStringArray("logentries", logentries); + + int[] fileselects = new int[fileSelectMap.size()]; + int k=0; + for (Utils.FileType key :fileSelectMap.keySet()){ + fileselects[k]=key.getValue(); + k++; + } + outState.putIntArray("fileselects",fileselects); + + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent result) { + if (requestCode == RESULT_INSTALLPKCS12 && resultCode == Activity.RESULT_OK) { + showCertDialog(); + } + + if (resultCode == Activity.RESULT_OK && requestCode >= CHOOSE_FILE_OFFSET) { + Utils.FileType type = Utils.FileType.getFileTypeByValue(requestCode - CHOOSE_FILE_OFFSET); + + + FileSelectLayout fs = fileSelectMap.get(type); + fs.parseResponse(result, this); + + String data = fs.getData(); + + switch (type){ + case USERPW_FILE: + ConfigParser.useEmbbedUserAuth(mResult, data); + break; + case PKCS12: + mResult.mPKCS12Filename = data; + break; + case TLS_AUTH_FILE: + mResult.mTLSAuthFilename = data; + break; + case CA_CERTIFICATE: + mResult.mCaFilename = data; + break; + case CLIENT_CERTIFICATE: + mResult.mClientCertFilename = data; + break; + case KEYFILE: + mResult.mClientKeyFilename = data; + break; + default: + Assert.fail(); + } + } + + super.onActivityResult(requestCode, resultCode, result); + } private void saveProfile() { Intent result = new Intent(); ProfileManager vpl = ProfileManager.getInstance(this); - setUniqueProfileName(vpl); + vpl.addProfile(mResult); vpl.saveProfile(this, mResult); vpl.saveProfileList(this); @@ -184,10 +227,13 @@ public class ConfigConverter extends ListActivity { - private void setUniqueProfileName(ProfileManager vpl) { + private String getUniqueProfileName(String possibleName) { + int i=0; - String newname = mPossibleName; + ProfileManager vpl = ProfileManager.getInstance(this); + + String newname = possibleName; // Default to if(mResult.mName!=null && !ConfigParser.CONVERTED_PROFILE.equals(mResult.mName)) @@ -201,7 +247,7 @@ public class ConfigConverter extends ListActivity { newname = getString(R.string.converted_profile_i,i); } - mResult.mName=newname; + return newname; } @Override @@ -210,12 +256,8 @@ public class ConfigConverter extends ListActivity { inflater.inflate(R.menu.import_menu, menu); return true; } - - private String embedFile(String filename) { - return embedFile(filename, false); - } - private String embedFile(String filename, boolean base64encode) + private String embedFile(String filename, Utils.FileType type) { if(filename==null) return null; @@ -224,27 +266,75 @@ public class ConfigConverter extends ListActivity { if(filename.startsWith(VpnProfile.INLINE_TAG)) return filename; - File possibleFile = findFile(filename); + File possibleFile = findFile(filename, type); if(possibleFile==null) return filename; else - return readFileContent(possibleFile,base64encode); + return readFileContent(possibleFile,type == Utils.FileType.PKCS12); } - private File findFile(String filename) { + private File findFile(String filename, Utils.FileType fileType) { File foundfile =findFileRaw(filename); - if (foundfile==null && filename!=null && !filename.equals("")) + if (foundfile==null && filename!=null && !filename.equals("")) { log(R.string.import_could_not_open,filename); + addFileSelectDialog(fileType); + } return foundfile; } - - - private File findFileRaw(String filename) + private void addFileSelectDialog(Utils.FileType type) { + int titleRes = 0; + String value=null; + switch (type) { + case KEYFILE: + titleRes = R.string.client_key_title; + if (mResult!=null) + value = mResult.mClientKeyFilename; + break; + case CLIENT_CERTIFICATE: + titleRes = R.string.client_certificate_title; + if (mResult!=null) + value = mResult.mClientCertFilename; + break; + case CA_CERTIFICATE: + titleRes = R.string.ca_title; + if (mResult!=null) + value = mResult.mCaFilename; + break; + case TLS_AUTH_FILE: + titleRes = R.string.tls_auth_file; + if (mResult!=null) + value = mResult.mTLSAuthFilename; + break; + case PKCS12: + titleRes = R.string.client_pkcs12_title; + if (mResult!=null) + value = mResult.mPKCS12Filename; + break; + } + + boolean isCert = type == Utils.FileType.CA_CERTIFICATE || type == Utils.FileType.CLIENT_CERTIFICATE; + FileSelectLayout fl = new FileSelectLayout(this,getString(titleRes), isCert); + fl.setData(value,this); + fileSelectMap.put(type,fl); + fl.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + + ((LinearLayout) findViewById(R.id.config_convert_root)).addView(fl, 1); + int i = getFileLayoutOffset(type); + fl.setCaller(this, i, type); + + } + + private int getFileLayoutOffset(Utils.FileType type) { + return CHOOSE_FILE_OFFSET + type.getValue(); + } + + + private File findFileRaw(String filename) { if(filename == null || filename.equals("")) return null; @@ -358,65 +448,98 @@ public class ConfigConverter extends ListActivity { } - mResult.mCaFilename = embedFile(mResult.mCaFilename); - mResult.mClientCertFilename = embedFile(mResult.mClientCertFilename); - mResult.mClientKeyFilename = embedFile(mResult.mClientKeyFilename); - mResult.mTLSAuthFilename = embedFile(mResult.mTLSAuthFilename); - mResult.mPKCS12Filename = embedFile(mResult.mPKCS12Filename,true); + mResult.mCaFilename = embedFile(mResult.mCaFilename, Utils.FileType.CA_CERTIFICATE); + mResult.mClientCertFilename = embedFile(mResult.mClientCertFilename, Utils.FileType.CLIENT_CERTIFICATE); + mResult.mClientKeyFilename = embedFile(mResult.mClientKeyFilename, Utils.FileType.KEYFILE); + mResult.mTLSAuthFilename = embedFile(mResult.mTLSAuthFilename, Utils.FileType.TLS_AUTH_FILE); + mResult.mPKCS12Filename = embedFile(mResult.mPKCS12Filename, Utils.FileType.PKCS12); if(mResult.mUsername == null && mResult.mPassword != null ){ - String data =embedFile(mResult.mPassword); - ConfigParser.useEmbbedUserAuth(mResult, data); - } + String data =embedFile(mResult.mPassword, Utils.FileType.USERPW_FILE); + ConfigParser.useEmbbedUserAuth(mResult, data); + } } + @Override + protected void onCreate(Bundle savedInstanceState) { - @Override - protected void onStart() { - super.onStart(); + setContentView(R.layout.config_converter); + + mArrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1); + getListView().setAdapter(mArrayAdapter); + + super.onCreate(savedInstanceState); - mArrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1); - getListView().setAdapter(mArrayAdapter); - final android.content.Intent intent = getIntent (); - - if (intent != null) - { - final android.net.Uri data = intent.getData (); - if (data != null) - { - //log(R.string.import_experimental); - log(R.string.importing_config,data.toString()); - try { - if(data.getScheme().equals("file") || + + if (savedInstanceState !=null && savedInstanceState.containsKey(VPNPROFILE)) { + mResult = (VpnProfile) savedInstanceState.getSerializable(VPNPROFILE); + mAliasName = savedInstanceState.getString("mAliasName"); + mArrayAdapter.addAll(savedInstanceState.getStringArray("logentries")); + for (int k: savedInstanceState.getIntArray("fileselects")) { + addFileSelectDialog(Utils.FileType.getFileTypeByValue(k)); + } + + return; + } + + + + final android.content.Intent intent = getIntent (); + + if (intent != null ) + { + final android.net.Uri data = intent.getData (); + if (data != null) + { + //log(R.string.import_experimental); + log(R.string.importing_config,data.toString()); + try { + String possibleName = null; + if(data.getScheme().equals("file") || data.getLastPathSegment().endsWith(".ovpn") || data.getLastPathSegment().endsWith(".conf")) { - mPossibleName = data.getLastPathSegment(); - if (mPossibleName.lastIndexOf('/')!=-1) - mPossibleName = mPossibleName.substring(mPossibleName.lastIndexOf('/')+1); - - if(mPossibleName!=null){ - mPossibleName =mPossibleName.replace(".ovpn", ""); - mPossibleName =mPossibleName.replace(".conf", ""); - } - } - InputStream is = getContentResolver().openInputStream(data); - mPathsegments = data.getPathSegments(); - - doImport(is); - } catch (FileNotFoundException e) { - log(R.string.import_content_resolve_error); - } - } - } + possibleName = data.getLastPathSegment(); + if (possibleName.lastIndexOf('/')!=-1) + possibleName = possibleName.substring(possibleName.lastIndexOf('/')+1); + + if(possibleName!=null){ + possibleName =possibleName.replace(".ovpn", ""); + possibleName =possibleName.replace(".conf", ""); + } + } + InputStream is = getContentResolver().openInputStream(data); + mPathsegments = data.getPathSegments(); + + doImport(is, possibleName); + + } catch (FileNotFoundException e) { + log(R.string.import_content_resolve_error); + } + } + + // We parsed the intent, relay on saved instance for restoring + setIntent(null); + } + + + } + + + @Override + protected void onStart() { + super.onStart(); + + + } private void log(String logmessage) { mArrayAdapter.add(logmessage); } - private void doImport(InputStream is) { + private void doImport(InputStream is, String newName) { ConfigParser cp = new ConfigParser(); try { InputStreamReader isr = new InputStreamReader(is); @@ -426,7 +549,9 @@ public class ConfigConverter extends ListActivity { mResult = vp; embedFiles(); displayWarnings(); - log(R.string.import_done); + mResult.mName = getUniqueProfileName(newName); + + log(R.string.import_done); return; } catch (IOException e) { @@ -462,4 +587,6 @@ public class ConfigConverter extends ListActivity { private void log(int ressourceId, Object... formatArgs) { log(getString(ressourceId,formatArgs)); } + + } diff --git a/src/de/blinkt/openvpn/core/NetworkSpace.java b/src/de/blinkt/openvpn/core/NetworkSpace.java index 3701c43d..821565b8 100644 --- a/src/de/blinkt/openvpn/core/NetworkSpace.java +++ b/src/de/blinkt/openvpn/core/NetworkSpace.java @@ -87,9 +87,9 @@ public class NetworkSpace { public String toString() { //String in = included ? "+" : "-"; if (isV4) - return String.format("%s/%d", getIPv4Address(), networkMask); + return String.format(Locale.US,"%s/%d", getIPv4Address(), networkMask); else - return String.format("%s/%d", getIPv6Address(), networkMask); + return String.format(Locale.US, "%s/%d", getIPv6Address(), networkMask); } ipAddress(BigInteger baseAddress, int mask, boolean included, boolean isV4) { @@ -112,7 +112,7 @@ public class NetworkSpace { assert (netAddress.longValue() <= 0xffffffffl); assert (netAddress.longValue() >= 0); long ip = netAddress.longValue(); - return String.format("%d.%d.%d.%d", (ip >> 24) % 256, (ip >> 16) % 256, (ip >> 8) % 256, ip % 256); + return String.format(Locale.US, "%d.%d.%d.%d", (ip >> 24) % 256, (ip >> 16) % 256, (ip >> 8) % 256, ip % 256); } String getIPv6Address() { @@ -123,7 +123,7 @@ public class NetworkSpace { Vector parts = new Vector(); while (r.compareTo(BigInteger.ZERO) == 1) { - parts.add(0, String.format("%x", r.mod(BigInteger.valueOf(256)).longValue())); + parts.add(0, String.format(Locale.US, "%x", r.mod(BigInteger.valueOf(256)).longValue())); r = r.shiftRight(16); } diff --git a/src/de/blinkt/openvpn/fragments/Settings_Basic.java b/src/de/blinkt/openvpn/fragments/Settings_Basic.java index f2fab505..4145c65f 100644 --- a/src/de/blinkt/openvpn/fragments/Settings_Basic.java +++ b/src/de/blinkt/openvpn/fragments/Settings_Basic.java @@ -35,7 +35,7 @@ import de.blinkt.openvpn.core.X509Utils; import java.security.cert.X509Certificate; -public class Settings_Basic extends Fragment implements View.OnClickListener, OnItemSelectedListener, Callback { +public class Settings_Basic extends Fragment implements View.OnClickListener, OnItemSelectedListener, Callback, FileSelectLayout.FileSelectCallback { private static final int CHOOSE_FILE_OFFSET = 1000; private static final int UPDATE_ALIAS = 20; @@ -66,7 +66,7 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On private void addFileSelectLayout (FileSelectLayout fsl, Utils.FileType type) { int i = fileselects.size() + CHOOSE_FILE_OFFSET; fileselects.put(i, fsl); - fsl.setFragment(this,i,type); + fsl.setCaller(this, i, type); } public void onCreate(Bundle savedInstanceState) { @@ -140,8 +140,8 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On mPassword = (EditText) mView.findViewById(R.id.auth_password); mKeyPassword = (EditText) mView.findViewById(R.id.key_password); - addFileSelectLayout(mCaCert, Utils.FileType.CERTIFICATE); - addFileSelectLayout(mClientCert, Utils.FileType.CERTIFICATE); + addFileSelectLayout(mCaCert, Utils.FileType.CA_CERTIFICATE); + addFileSelectLayout(mClientCert, Utils.FileType.CLIENT_CERTIFICATE); addFileSelectLayout(mClientKey, Utils.FileType.KEYFILE); addFileSelectLayout(mpkcs12, Utils.FileType.PKCS12); mCaCert.setShowClear(); diff --git a/src/de/blinkt/openvpn/fragments/Utils.java b/src/de/blinkt/openvpn/fragments/Utils.java index d7a144ed..f13b1987 100644 --- a/src/de/blinkt/openvpn/fragments/Utils.java +++ b/src/de/blinkt/openvpn/fragments/Utils.java @@ -7,6 +7,7 @@ import android.net.Uri; import android.os.Build; import android.util.Base64; import android.webkit.MimeTypeMap; +import junit.framework.Assert; import java.io.*; import java.util.TreeSet; @@ -28,7 +29,8 @@ public class Utils { extensions.add("p12"); extensions.add("pfx"); break; - case CERTIFICATE: + case CLIENT_CERTIFICATE: + case CA_CERTIFICATE: i.setType("application/x-pem-file"); supportedMimeTypes.add("application/x-x509-ca-cert"); supportedMimeTypes.add("application/x-x509-user-cert"); @@ -61,6 +63,9 @@ public class Utils { extensions.add("txt"); extensions.add("key"); break; + case USERPW_FILE: + Assert.fail(); + break; } MimeTypeMap mtm = MimeTypeMap.getSingleton(); @@ -78,11 +83,45 @@ public class Utils { } public enum FileType { - PKCS12, - CERTIFICATE, - OVPN_CONFIG, - KEYFILE, - TLS_AUTH_FILE + PKCS12(0), + CLIENT_CERTIFICATE(1), + CA_CERTIFICATE(2), + OVPN_CONFIG(3), + KEYFILE(4), + TLS_AUTH_FILE(5), + USERPW_FILE(6); + + private int value; + + FileType(int i) { + value=i; + } + + public static FileType getFileTypeByValue(int value) + { + switch(value) { + case 0: + return PKCS12; + case 1: + return CLIENT_CERTIFICATE; + case 2: + return CA_CERTIFICATE; + case 3: + return OVPN_CONFIG; + case 4: + return KEYFILE; + case 5: + return TLS_AUTH_FILE; + case 6: + return USERPW_FILE; + default: + return null; + } + } + + public int getValue() { + return value; + } } static private byte[] readBytesFromStream(InputStream input) throws IOException { diff --git a/src/de/blinkt/openvpn/views/FileSelectLayout.java b/src/de/blinkt/openvpn/views/FileSelectLayout.java index 18a2a766..04392b47 100644 --- a/src/de/blinkt/openvpn/views/FileSelectLayout.java +++ b/src/de/blinkt/openvpn/views/FileSelectLayout.java @@ -1,13 +1,10 @@ package de.blinkt.openvpn.views; -import android.net.Uri; -import android.util.Base64; import de.blinkt.openvpn.R; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.activities.FileSelect; import de.blinkt.openvpn.core.VpnStatus; import de.blinkt.openvpn.core.X509Utils; -import android.app.Fragment; import android.content.Context; import android.content.Intent; import android.content.res.TypedArray; @@ -44,10 +41,17 @@ public class FileSelectLayout extends LinearLayout implements OnClickListener { } } - private final boolean mIsCertificate; + public interface FileSelectCallback { + + String getString(int res); + + void startActivityForResult(Intent startFC, int mTaskId); + } + + private boolean mIsCertificate; private TextView mDataView; private String mData; - private Fragment mFragment; + private FileSelectCallback mFragment; private int mTaskId; private Button mSelectButton; private Utils.FileType fileType; @@ -57,12 +61,27 @@ public class FileSelectLayout extends LinearLayout implements OnClickListener { public FileSelectLayout(Context context, AttributeSet attrset) { super(context, attrset); - inflate(getContext(), R.layout.file_select, this); TypedArray ta = context.obtainStyledAttributes(attrset, R.styleable.FileSelectLayout); - mTitle = ta.getString(R.styleable.FileSelectLayout_title); - mIsCertificate = ta.getBoolean(R.styleable.FileSelectLayout_certificate, true); + setupViews(ta.getString(R.styleable.FileSelectLayout_title), ta.getBoolean(R.styleable.FileSelectLayout_certificate, true)); + + ta.recycle(); + } + + public FileSelectLayout (Context context, String title, boolean isCerticate) + { + super(context); + + setupViews(title, isCerticate); + + } + + private void setupViews(String title, boolean isCertificate) { + inflate(getContext(), R.layout.file_select, this); + + mTitle = title; + mIsCertificate = isCertificate; TextView tview = (TextView) findViewById(R.id.file_title); tview.setText(mTitle); @@ -71,11 +90,10 @@ public class FileSelectLayout extends LinearLayout implements OnClickListener { mDataDetails = (TextView) findViewById(R.id.file_selected_description); mSelectButton = (Button) findViewById(R.id.file_select_button); mSelectButton.setOnClickListener(this); - - ta.recycle(); } - public void setFragment(Fragment fragment, int i, Utils.FileType ft) { + + public void setCaller(FileSelectCallback fragment, int i, Utils.FileType ft) { mTaskId = i; mFragment = fragment; fileType = ft; -- cgit v1.2.3