diff options
| author | Arne Schwabe <arne@rfc2549.org> | 2014-01-16 23:13:41 +0100 | 
|---|---|---|
| committer | Arne Schwabe <arne@rfc2549.org> | 2014-01-16 23:13:41 +0100 | 
| commit | 5ee6a9d698e6231f37a6d2a47e05459d107fb049 (patch) | |
| tree | 04565f68ac3b3de05e44f6439df6a1f9a847ec5f | |
| parent | fa8d545becf246b6f09d2fb6392d4cc25788346f (diff) | |
Switch to android file dialog on 4.4 for importing pkcs12, certificates and key files
| -rw-r--r-- | src/de/blinkt/openvpn/activities/FileSelect.java | 2 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/fragments/Settings_Basic.java | 29 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/views/FileSelectLayout.java | 277 | 
3 files changed, 209 insertions, 99 deletions
diff --git a/src/de/blinkt/openvpn/activities/FileSelect.java b/src/de/blinkt/openvpn/activities/FileSelect.java index 405e0dbf..50584063 100644 --- a/src/de/blinkt/openvpn/activities/FileSelect.java +++ b/src/de/blinkt/openvpn/activities/FileSelect.java @@ -154,7 +154,7 @@ public class FileSelect extends Activity {  		}  	} -	private byte[] readBytesFromFile(File file) throws IOException { +	static private byte[] readBytesFromFile(File file) throws IOException {  		InputStream input = new FileInputStream(file);  		long len= file.length(); diff --git a/src/de/blinkt/openvpn/fragments/Settings_Basic.java b/src/de/blinkt/openvpn/fragments/Settings_Basic.java index d18a2ed1..cf4d22d1 100644 --- a/src/de/blinkt/openvpn/fragments/Settings_Basic.java +++ b/src/de/blinkt/openvpn/fragments/Settings_Basic.java @@ -40,8 +40,6 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On  	private static final int CHOOSE_FILE_OFFSET = 1000;  	private static final int UPDATE_ALIAS = 20; - -  	private TextView mServerAddress;  	private TextView mServerPort;  	private FileSelectLayout mClientCert; @@ -66,16 +64,16 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On -    private void addFileSelectLayout (FileSelectLayout fsl) { +    private void addFileSelectLayout (FileSelectLayout fsl, FileSelectLayout.FileType type) {  		int i = fileselects.size() + CHOOSE_FILE_OFFSET;  		fileselects.put(i, fsl); -		fsl.setFragment(this,i); +		fsl.setFragment(this,i,type);  	}  	public void onCreate(Bundle savedInstanceState) {  		super.onCreate(savedInstanceState); -		String profileuuid =getArguments().getString(getActivity().getPackageName() + ".profileUUID"); -		mProfile=ProfileManager.get(getActivity(),profileuuid); +		String profileUuid = getArguments().getString(getActivity().getPackageName() + ".profileUUID"); +		mProfile=ProfileManager.get(getActivity(),profileUuid);  		getActivity().setTitle(getString(R.string.edit_profile_title, mProfile.getName()));  	} @@ -143,13 +141,10 @@ 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); -		addFileSelectLayout(mClientCert); -		addFileSelectLayout(mClientKey); -		addFileSelectLayout(mpkcs12); -		mpkcs12.setBase64Encode(); +		addFileSelectLayout(mCaCert, FileSelectLayout.FileType.CERTIFICATE); +		addFileSelectLayout(mClientCert, FileSelectLayout.FileType.CERTIFICATE); +		addFileSelectLayout(mClientKey, FileSelectLayout.FileType.KEYFILE); +		addFileSelectLayout(mpkcs12, FileSelectLayout.FileType.PKCS12);  		mCaCert.setShowClear();  		mType.setOnItemSelectedListener(this); @@ -168,8 +163,8 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On  	@Override  	public void onStart() {  		super.onStart(); -		String profileuuid =getArguments().getString(getActivity().getPackageName() + ".profileUUID"); -		mProfile=ProfileManager.get(getActivity(),profileuuid); +		String profileUuid =getArguments().getString(getActivity().getPackageName() + ".profileUUID"); +		mProfile=ProfileManager.get(getActivity(),profileUuid);  		loadPreferences();  	} @@ -177,9 +172,9 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On  	@Override  	public void onActivityResult(int request, int result, Intent data) {  		if (result == Activity.RESULT_OK && request >= CHOOSE_FILE_OFFSET) { -			String filedata = data.getStringExtra(FileSelect.RESULT_DATA); +  			FileSelectLayout fsl = fileselects.get(request); -			fsl.setData(filedata, getActivity()); +            fsl.parseResponse(data, getActivity());  			savePreferences(); diff --git a/src/de/blinkt/openvpn/views/FileSelectLayout.java b/src/de/blinkt/openvpn/views/FileSelectLayout.java index 7ee96884..57ccd895 100644 --- a/src/de/blinkt/openvpn/views/FileSelectLayout.java +++ b/src/de/blinkt/openvpn/views/FileSelectLayout.java @@ -1,8 +1,17 @@  package de.blinkt.openvpn.views; +import android.annotation.TargetApi; +import android.app.Activity; +import android.net.Uri; +import android.os.Build; +import android.text.TextUtils; +import android.text.style.CharacterStyle; +import android.util.Base64; +import android.webkit.MimeTypeMap;  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; @@ -15,91 +24,197 @@ import android.widget.Button;  import android.widget.LinearLayout;  import android.widget.TextView; +import java.io.*; +import java.util.TreeSet; +import java.util.Vector; + +import static android.os.Build.*; +  public class FileSelectLayout extends LinearLayout implements OnClickListener { +    public void parseResponse(Intent data, Context c) { +        if (VERSION.SDK_INT < VERSION_CODES.KITKAT) { +            String fileData = data.getStringExtra(FileSelect.RESULT_DATA); +            setData(fileData, c); +        } else if (data != null) { +            Uri uri = data.getData(); +            try { +                byte[] fileData = readBytesFromStream(c.getContentResolver().openInputStream(uri)); +                String newData = null; +                switch (fileType) { +                    case CERTIFICATE: +                    case KEYFILE: +                        newData = new String(fileData, "UTF-8"); +                        break; +                    case PKCS12: +                        newData = Base64.encodeToString(fileData, Base64.DEFAULT); +                        break; +                } +                setData(VpnProfile.INLINE_TAG + newData, c); + +            } catch (IOException e) { +                VpnStatus.logException(e); +            } + + +        } +    } + +    static private byte[] readBytesFromStream(InputStream input) throws IOException { + +        ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + +        int nRead; +        byte[] data = new byte[16384]; + +        while ((nRead = input.read(data, 0, data.length)) != -1) { +            buffer.write(data, 0, nRead); +        } + +        buffer.flush(); +        input.close(); +        return buffer.toByteArray(); +    } + +    public enum FileType { +        PKCS12, +        CERTIFICATE, +        KEYFILE +    } +      private final boolean mIsCertificate;      private TextView mDataView; -	private String mData; -	private Fragment mFragment; -	private int mTaskId; -	private Button mSelectButton; -	private boolean mBase64Encode; -	private String mTitle; -	private boolean mShowClear; -	private TextView mDataDetails; - -	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); - -		TextView tview = (TextView) findViewById(R.id.file_title); -		tview.setText(mTitle); - -		mDataView = (TextView) findViewById(R.id.file_selected_item); -		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) -	{ -		mTaskId = i; -		mFragment = fragment; -	} - -	public void getCertificateFileDialog() { -		Intent startFC = new Intent(getContext(),FileSelect.class); -		startFC.putExtra(FileSelect.START_DATA, mData); -		startFC.putExtra(FileSelect.WINDOW_TITLE,mTitle); -		if(mBase64Encode) -			startFC.putExtra(FileSelect.DO_BASE64_ENCODE, true); -		if(mShowClear) -			startFC.putExtra(FileSelect.SHOW_CLEAR_BUTTON, true); -		mFragment.startActivityForResult(startFC,mTaskId); -	} - - -	public String getData() { -		return mData; -	} - -	public void setData(String data, Context c) { -		mData = data; -		if(data==null) {  -			mDataView.setText(mFragment.getString(R.string.no_data)); -			mDataDetails.setText(""); -		}else { -			if(mData.startsWith(VpnProfile.INLINE_TAG)) -				mDataView.setText(R.string.inline_file_data); -			else -				mDataView.setText(data); -            if(mIsCertificate) -			    mDataDetails.setText(X509Utils.getCertificateFriendlyName(c,data)); -		} - -	} - -	@Override -	public void onClick(View v) { -		if(v == mSelectButton) { -			getCertificateFileDialog(); -		} -	} - -	public void setBase64Encode() { -		mBase64Encode =true; -	} - -	public void setShowClear() { -		mShowClear=true; -	} +    private String mData; +    private Fragment mFragment; +    private int mTaskId; +    private Button mSelectButton; +    private FileType fileType; +    private String mTitle; +    private boolean mShowClear; +    private TextView mDataDetails; + +    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); + +        TextView tview = (TextView) findViewById(R.id.file_title); +        tview.setText(mTitle); + +        mDataView = (TextView) findViewById(R.id.file_selected_item); +        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, FileType ft) { +        mTaskId = i; +        mFragment = fragment; +        fileType = ft; +    } + +    public void getCertificateFileDialog() { +        Intent startFC = new Intent(getContext(), FileSelect.class); +        startFC.putExtra(FileSelect.START_DATA, mData); +        startFC.putExtra(FileSelect.WINDOW_TITLE, mTitle); +        if (fileType == FileType.PKCS12) +            startFC.putExtra(FileSelect.DO_BASE64_ENCODE, true); +        if (mShowClear) +            startFC.putExtra(FileSelect.SHOW_CLEAR_BUTTON, true); + +        mFragment.startActivityForResult(startFC, mTaskId); +    } + + +    public String getData() { +        return mData; +    } + +    public void setData(String data, Context c) { +        mData = data; +        if (data == null) { +            mDataView.setText(mFragment.getString(R.string.no_data)); +            mDataDetails.setText(""); +        } else { +            if (mData.startsWith(VpnProfile.INLINE_TAG)) +                mDataView.setText(R.string.inline_file_data); +            else +                mDataView.setText(data); +            if (mIsCertificate) +                mDataDetails.setText(X509Utils.getCertificateFriendlyName(c, data)); +        } + +    } + +    @Override +    public void onClick(View v) { +        if (v == mSelectButton) { +            if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) +                startFilePicker(); +            else +                getCertificateFileDialog(); +        } +    } + + +    @TargetApi(VERSION_CODES.KITKAT) +    private void startFilePicker() { + + +        Intent i = new Intent(Intent.ACTION_OPEN_DOCUMENT); +        i.addCategory(Intent.CATEGORY_OPENABLE); +        TreeSet<String> supportedMimeTypes = new TreeSet<String>(); +        Vector<String> extensions = new Vector<String>(); + +        switch (fileType) { +            case PKCS12: +                i.setType("application/x-pkcs12"); +                supportedMimeTypes.add("application/x-pkcs12"); +                extensions.add("p12"); +                extensions.add("pfx"); +                break; +            case CERTIFICATE: +                i.setType("application/x-pem-file"); +                supportedMimeTypes.add("application/x-x509-ca-cert"); +                supportedMimeTypes.add("application/x-x509-user-cert"); +                supportedMimeTypes.add("application/x-pem-file"); +                supportedMimeTypes.add("text/plain"); + +                extensions.add("pem"); +                extensions.add("crt"); +                break; +            case KEYFILE: +                i.setType("application/x-pem-file"); +                supportedMimeTypes.add("application/x-pem-file"); +                supportedMimeTypes.add("application/pkcs8"); +                extensions.add("key"); +                break; +        } + +        MimeTypeMap mtm = MimeTypeMap.getSingleton(); + +        for (String ext : new String[]{"ovpn", "conf"}) { +            String mimeType = mtm.getMimeTypeFromExtension(ext); +            if (mimeType != null) +                supportedMimeTypes.add(mimeType); +            else +                supportedMimeTypes.add("application/octet-stream"); +        } + + +        i.putExtra(Intent.EXTRA_MIME_TYPES, supportedMimeTypes.toArray(new String[supportedMimeTypes.size()])); +        mFragment.startActivityForResult(i, mTaskId); +    } + +    public void setShowClear() { +        mShowClear = true; +    }  }  | 
