diff options
author | Arne Schwabe <arne@rfc2549.org> | 2012-05-11 00:46:33 +0200 |
---|---|---|
committer | Arne Schwabe <arne@rfc2549.org> | 2012-05-11 00:46:33 +0200 |
commit | 480535d1de23e30780b3ae5a166cdc59a22a2adc (patch) | |
tree | af278c4a7243807df6cf0e7774fd7cc810f7d1a9 | |
parent | 7ecb6349023b144d485bf44a9e7a7149016930f7 (diff) |
Rework FIle selection dialog.
Include possibility to include file content in VPN Profile. Allows safer storage of Certifcates and keys. (closes issue #13)
-rw-r--r-- | AndroidManifest.xml | 5 | ||||
-rw-r--r-- | res/layout/file_dialog.xml | 13 | ||||
-rw-r--r-- | res/layout/file_dialog_inline.xml | 22 | ||||
-rw-r--r-- | res/layout/file_dialog_main.xml | 117 | ||||
-rw-r--r-- | res/values/strings.xml | 8 | ||||
-rw-r--r-- | src/com/lamerman/FileDialog.java | 388 | ||||
-rw-r--r-- | src/com/lamerman/SelectionMode.java | 7 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/ConfigParser.java | 2 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/FaqFragment.java | 2 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/FileSelect.java | 145 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/FileSelectLayout.java | 20 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/FileSelectionFragment.java | 244 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/InlineFileTab.java | 65 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/LaunchVPN.java | 1 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/OpenVPN.java | 2 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/OpenVPNThread.java | 2 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/OpenVpnService.java | 1 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/Settings_Authentication.java | 28 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/Settings_Basic.java | 8 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/VpnProfile.java | 42 |
20 files changed, 606 insertions, 516 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 1103b67..61c5f58 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -29,12 +29,13 @@ <application android:icon="@drawable/icon" android:label="@string/app" > - <activity android:name="com.lamerman.FileDialog" /> + <activity android:name=".FileSelectionFragment" /> <activity android:name=".AboutFragment" /> <activity android:name=".VPNPreferences" /> <activity android:name=".LogWindow" android:label="OpenVPN Log" /> + <activity android:name=".FileSelect" /> <activity android:name=".MainActivity" > <intent-filter> <action android:name="android.intent.action.MAIN" /> @@ -73,4 +74,4 @@ </activity-alias> </application> -</manifest> +</manifest>
\ No newline at end of file diff --git a/res/layout/file_dialog.xml b/res/layout/file_dialog.xml new file mode 100644 index 0000000..8e07ce3 --- /dev/null +++ b/res/layout/file_dialog.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" > + + <LinearLayout + android:id="@+id/fragment_place" + android:layout_width="match_parent" + android:layout_height="wrap_content" > + </LinearLayout> + +</LinearLayout>
\ No newline at end of file diff --git a/res/layout/file_dialog_inline.xml b/res/layout/file_dialog_inline.xml new file mode 100644 index 0000000..61e3913 --- /dev/null +++ b/res/layout/file_dialog_inline.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" > +<!-- The header already states Inline File + <TextView + android:id="@+id/textView1" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Inline File Data" + android:textAppearance="?android:attr/textAppearanceMedium" /> + --> + <EditText + android:id="@+id/inlineFileData" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:inputType="textMultiLine|textNoSuggestions" + android:textAppearance="?android:attr/textAppearanceSmall" /> + + +</LinearLayout>
\ No newline at end of file diff --git a/res/layout/file_dialog_main.xml b/res/layout/file_dialog_main.xml index c803522..2f88ffb 100644 --- a/res/layout/file_dialog_main.xml +++ b/res/layout/file_dialog_main.xml @@ -1,66 +1,53 @@ <?xml version="1.0" encoding="utf-8"?> -<RelativeLayout android:id="@+id/relativeLayout01" - xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="vertical" android:layout_width="fill_parent" - android:layout_height="fill_parent"> - - <LinearLayout android:id="@+id/fdLinearLayoutList" - android:orientation="vertical" android:layout_width="fill_parent" - android:layout_height="wrap_content" android:layout_alignParentBottom="true"> - - <LinearLayout android:id="@+id/fdLinearLayoutSelect" - android:orientation="vertical" android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_alignParentBottom="true" android:paddingLeft="10dp" - android:paddingRight="10dp" android:paddingBottom="5dp"> - - <LinearLayout android:orientation="horizontal" - android:layout_width="fill_parent" android:layout_height="fill_parent"> - <Button android:id="@+id/fdButtonNew" android:layout_height="wrap_content" - android:layout_width="0dip" android:layout_weight=".3" - android:text="@string/nnew"></Button> - <Button android:id="@+id/fdButtonSelect" android:layout_height="wrap_content" - android:layout_width="0dip" android:layout_weight=".7" - android:text="@string/select"></Button> - </LinearLayout> - </LinearLayout> - - <LinearLayout android:id="@+id/fdLinearLayoutCreate" - android:orientation="vertical" android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_alignParentBottom="true" android:paddingLeft="10dp" - android:paddingRight="10dp" android:paddingBottom="5dp"> - <TextView android:id="@+id/textViewFilename" android:text="@string/file_name" - android:layout_width="fill_parent" android:layout_height="wrap_content" /> - <EditText android:text="" android:id="@+id/fdEditTextFile" - android:layout_width="fill_parent" android:layout_height="wrap_content"></EditText> - - <LinearLayout android:orientation="horizontal" - android:layout_width="fill_parent" android:layout_height="fill_parent"> - <Button android:id="@+id/fdButtonCancel" android:layout_height="wrap_content" - android:layout_width="0dip" android:layout_weight=".3" - android:text="@string/cancel"></Button> - <Button android:id="@+id/fdButtonCreate" android:layout_height="wrap_content" - android:layout_width="0dip" android:layout_weight=".7" - android:text="@string/create"></Button> - </LinearLayout> - </LinearLayout> - - </LinearLayout> - - <LinearLayout android:orientation="vertical" - android:layout_width="fill_parent" android:layout_height="fill_parent" - android:layout_above="@+id/fdLinearLayoutList"> - <TextView android:id="@+id/path" android:layout_width="fill_parent" - android:layout_height="wrap_content" /> - <ListView android:id="@android:id/list" android:layout_width="fill_parent" - android:layout_height="fill_parent" /> - <TextView android:id="@android:id/empty" - android:layout_width="fill_parent" android:layout_height="fill_parent" - android:text="@string/no_data" /> - </LinearLayout> - - - - -</RelativeLayout> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/relativeLayout01" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" > + + <LinearLayout + android:id="@+id/fdLinearLayoutList" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:orientation="horizontal" > + + <Button + android:id="@+id/importfile" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/import_file" > + </Button> + + <Button + android:id="@+id/fdButtonSelect" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/select" > + </Button> + </LinearLayout> + + <LinearLayout + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:layout_above="@+id/fdLinearLayoutList" + android:orientation="vertical" > + + <TextView + android:id="@+id/path" + android:layout_width="fill_parent" + android:layout_height="wrap_content" /> + + <ListView + android:id="@android:id/list" + android:layout_width="fill_parent" + android:layout_height="fill_parent" /> + + <TextView + android:id="@android:id/empty" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:text="@string/no_data" /> + </LinearLayout> + +</RelativeLayout>
\ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index 9073c0b..2b7c82f 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -188,5 +188,11 @@ <string name="encryption">Encryption</string> <string name="cipher_dialog_title">Enter Encryption method</string> <string name="chipher_dialog_message">Enter the cipher key for openvpn. Leave empty to use default cipher</string> - <string name="settings_auth">Authentication/Encryption</string> + <string name="settings_auth">Authentication/Encryption</string> + <string name="file_explorer_tab">File Explorer</string> + <string name="inline_file_tab">Inline File</string> + <string name="import_file">Import</string> + <string name="error_importing_file">Error importing File</string> + <string name="import_error_message">Could not import File from Filesystem</string> + <string name="inline_file_data">[[Inline file data]]</string> </resources> diff --git a/src/com/lamerman/FileDialog.java b/src/com/lamerman/FileDialog.java deleted file mode 100644 index a5c6944..0000000 --- a/src/com/lamerman/FileDialog.java +++ /dev/null @@ -1,388 +0,0 @@ -package com.lamerman; - -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.TreeMap; - -import android.app.AlertDialog; -import android.app.ListActivity; -import android.content.DialogInterface; -import android.os.Bundle; -import android.view.KeyEvent; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.inputmethod.InputMethodManager; -import android.widget.Button; -import android.widget.EditText; -import android.widget.LinearLayout; -import android.widget.ListView; -import android.widget.SimpleAdapter; -import android.widget.TextView; -import de.blinkt.openvpn.R; - -/** - * Activity para escolha de arquivos/diretorios. - * - * @author android - * - */ -public class FileDialog extends ListActivity { - - /** - * Chave de um item da lista de paths. - */ - private static final String ITEM_KEY = "key"; - - /** - * Imagem de um item da lista de paths (diretorio ou arquivo). - */ - private static final String ITEM_IMAGE = "image"; - - /** - * Diretorio raiz. - */ - private static final String ROOT = "/"; - - /** - * Parametro de entrada da Activity: path inicial. Padrao: ROOT. - */ - public static final String START_PATH = "START_PATH"; - - /** - * Parametro de entrada da Activity: filtro de formatos de arquivos. Padrao: - * null. - */ - public static final String FORMAT_FILTER = "FORMAT_FILTER"; - - /** - * Parametro de saida da Activity: path escolhido. Padrao: null. - */ - public static final String RESULT_PATH = "RESULT_PATH"; - - /** - * Parametro de entrada da Activity: tipo de selecao: pode criar novos paths - * ou nao. Padrao: nao permite. - * - * @see {@link SelectionMode} - */ - public static final String SELECTION_MODE = "SELECTION_MODE"; - - /** - * Parametro de entrada da Activity: se e permitido escolher diretorios. - * Padrao: falso. - */ - public static final String CAN_SELECT_DIR = "CAN_SELECT_DIR"; - - private List<String> path = null; - private TextView myPath; - private EditText mFileName; - private ArrayList<HashMap<String, Object>> mList; - - private Button selectButton; - - private LinearLayout layoutSelect; - private LinearLayout layoutCreate; - private InputMethodManager inputManager; - private String parentPath; - private String currentPath = ROOT; - - private int selectionMode = SelectionMode.MODE_CREATE; - - private String[] formatFilter = null; - - private boolean canSelectDir = false; - - private File selectedFile; - private HashMap<String, Integer> lastPositions = new HashMap<String, Integer>(); - - /** - * Called when the activity is first created. Configura todos os parametros - * de entrada e das VIEWS.. - */ - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setResult(RESULT_CANCELED, getIntent()); - - setContentView(R.layout.file_dialog_main); - myPath = (TextView) findViewById(R.id.path); - mFileName = (EditText) findViewById(R.id.fdEditTextFile); - - inputManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); - - selectButton = (Button) findViewById(R.id.fdButtonSelect); - selectButton.setEnabled(false); - selectButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - if (selectedFile != null) { - getIntent().putExtra(RESULT_PATH, selectedFile.getPath()); - setResult(RESULT_OK, getIntent()); - finish(); - } - } - }); - - final Button newButton = (Button) findViewById(R.id.fdButtonNew); - newButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - setCreateVisible(v); - - mFileName.setText(""); - mFileName.requestFocus(); - } - }); - - selectionMode = getIntent().getIntExtra(SELECTION_MODE, SelectionMode.MODE_CREATE); - - formatFilter = getIntent().getStringArrayExtra(FORMAT_FILTER); - - canSelectDir = getIntent().getBooleanExtra(CAN_SELECT_DIR, false); - - if (selectionMode == SelectionMode.MODE_OPEN) { - newButton.setEnabled(false); - newButton.setVisibility(View.GONE); - } - - layoutSelect = (LinearLayout) findViewById(R.id.fdLinearLayoutSelect); - layoutCreate = (LinearLayout) findViewById(R.id.fdLinearLayoutCreate); - layoutCreate.setVisibility(View.GONE); - - final Button cancelButton = (Button) findViewById(R.id.fdButtonCancel); - cancelButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - setSelectVisible(v); - } - - }); - final Button createButton = (Button) findViewById(R.id.fdButtonCreate); - createButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - if (mFileName.getText().length() > 0) { - getIntent().putExtra(RESULT_PATH, currentPath + "/" + mFileName.getText()); - setResult(RESULT_OK, getIntent()); - finish(); - } - } - }); - - String startPath = getIntent().getStringExtra(START_PATH); - startPath = startPath != null ? startPath : ROOT; - if (canSelectDir) { - File file = new File(startPath); - selectedFile = file; - selectButton.setEnabled(true); - } - getDir(startPath); - } - - private void getDir(String dirPath) { - - boolean useAutoSelection = dirPath.length() < currentPath.length(); - - Integer position = lastPositions.get(parentPath); - - getDirImpl(dirPath); - - if (position != null && useAutoSelection) { - getListView().setSelection(position); - } - - } - - /** - * Monta a estrutura de arquivos e diretorios filhos do diretorio fornecido. - * - * @param dirPath - * Diretorio pai. - */ - private void getDirImpl(final String dirPath) { - - currentPath = dirPath; - - final List<String> item = new ArrayList<String>(); - path = new ArrayList<String>(); - mList = new ArrayList<HashMap<String, Object>>(); - - File f = new File(currentPath); - File[] files = f.listFiles(); - if (files == null) { - currentPath = ROOT; - f = new File(currentPath); - files = f.listFiles(); - } - myPath.setText(getText(R.string.location) + ": " + currentPath); - - if (!currentPath.equals(ROOT)) { - - item.add(ROOT); - addItem(ROOT, R.drawable.folder); - path.add(ROOT); - - item.add("../"); - addItem("../", R.drawable.folder); - path.add(f.getParent()); - parentPath = f.getParent(); - - } - - TreeMap<String, String> dirsMap = new TreeMap<String, String>(); - TreeMap<String, String> dirsPathMap = new TreeMap<String, String>(); - TreeMap<String, String> filesMap = new TreeMap<String, String>(); - TreeMap<String, String> filesPathMap = new TreeMap<String, String>(); - for (File file : files) { - if (file.isDirectory()) { - String dirName = file.getName(); - dirsMap.put(dirName, dirName); - dirsPathMap.put(dirName, file.getPath()); - } else { - final String fileName = file.getName(); - final String fileNameLwr = fileName.toLowerCase(); - // se ha um filtro de formatos, utiliza-o - if (formatFilter != null) { - boolean contains = false; - for (int i = 0; i < formatFilter.length; i++) { - final String formatLwr = formatFilter[i].toLowerCase(); - if (fileNameLwr.endsWith(formatLwr)) { - contains = true; - break; - } - } - if (contains) { - filesMap.put(fileName, fileName); - filesPathMap.put(fileName, file.getPath()); - } - // senao, adiciona todos os arquivos - } else { - filesMap.put(fileName, fileName); - filesPathMap.put(fileName, file.getPath()); - } - } - } - item.addAll(dirsMap.tailMap("").values()); - item.addAll(filesMap.tailMap("").values()); - path.addAll(dirsPathMap.tailMap("").values()); - path.addAll(filesPathMap.tailMap("").values()); - - SimpleAdapter fileList = new SimpleAdapter(this, mList, R.layout.file_dialog_row, new String[] { - ITEM_KEY, ITEM_IMAGE }, new int[] { R.id.fdrowtext, R.id.fdrowimage }); - - for (String dir : dirsMap.tailMap("").values()) { - addItem(dir, R.drawable.folder); - } - - for (String file : filesMap.tailMap("").values()) { - addItem(file, R.drawable.file); - } - - fileList.notifyDataSetChanged(); - - setListAdapter(fileList); - - } - - private void addItem(String fileName, int imageId) { - HashMap<String, Object> item = new HashMap<String, Object>(); - item.put(ITEM_KEY, fileName); - item.put(ITEM_IMAGE, imageId); - mList.add(item); - } - - /** - * Quando clica no item da lista, deve-se: 1) Se for diretorio, abre seus - * arquivos filhos; 2) Se puder escolher diretorio, define-o como sendo o - * path escolhido. 3) Se for arquivo, define-o como path escolhido. 4) Ativa - * botao de selecao. - */ - @Override - protected void onListItemClick(ListView l, View v, int position, long id) { - - File file = new File(path.get(position)); - - setSelectVisible(v); - - if (file.isDirectory()) { - selectButton.setEnabled(false); - if (file.canRead()) { - lastPositions.put(currentPath, position); - getDir(path.get(position)); - if (canSelectDir) { - selectedFile = file; - v.setSelected(true); - selectButton.setEnabled(true); - } - } else { - new AlertDialog.Builder(this).setIcon(R.drawable.icon) - .setTitle("[" + file.getName() + "] " + getText(R.string.cant_read_folder)) - .setPositiveButton("OK", new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - - } - }).show(); - } - } else { - selectedFile = file; - v.setSelected(true); - selectButton.setEnabled(true); - } - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if ((keyCode == KeyEvent.KEYCODE_BACK)) { - selectButton.setEnabled(false); - - if (layoutCreate.getVisibility() == View.VISIBLE) { - layoutCreate.setVisibility(View.GONE); - layoutSelect.setVisibility(View.VISIBLE); - } else { - if (!currentPath.equals(ROOT)) { - getDir(parentPath); - } else { - return super.onKeyDown(keyCode, event); - } - } - - return true; - } else { - return super.onKeyDown(keyCode, event); - } - } - - /** - * Define se o botao de CREATE e visivel. - * - * @param v - */ - private void setCreateVisible(View v) { - layoutCreate.setVisibility(View.VISIBLE); - layoutSelect.setVisibility(View.GONE); - - inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0); - selectButton.setEnabled(false); - } - - /** - * Define se o botao de SELECT e visivel. - * - * @param v - */ - private void setSelectVisible(View v) { - layoutCreate.setVisibility(View.GONE); - layoutSelect.setVisibility(View.VISIBLE); - - inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0); - selectButton.setEnabled(false); - } -} diff --git a/src/com/lamerman/SelectionMode.java b/src/com/lamerman/SelectionMode.java deleted file mode 100644 index 3c05dfa..0000000 --- a/src/com/lamerman/SelectionMode.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.lamerman; - -public class SelectionMode { - public static final int MODE_CREATE = 0; - - public static final int MODE_OPEN = 1; -} diff --git a/src/de/blinkt/openvpn/ConfigParser.java b/src/de/blinkt/openvpn/ConfigParser.java index 8497330..97ca639 100644 --- a/src/de/blinkt/openvpn/ConfigParser.java +++ b/src/de/blinkt/openvpn/ConfigParser.java @@ -11,7 +11,7 @@ import java.util.Vector; // And rember, this is valid :) // --<foo> // bar -// </bar> +// </foo> public class ConfigParser { diff --git a/src/de/blinkt/openvpn/FaqFragment.java b/src/de/blinkt/openvpn/FaqFragment.java index 94fc959..2697994 100644 --- a/src/de/blinkt/openvpn/FaqFragment.java +++ b/src/de/blinkt/openvpn/FaqFragment.java @@ -1,12 +1,10 @@ package de.blinkt.openvpn; import android.app.Fragment; -import android.content.pm.PackageManager.NameNotFoundException; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; public class FaqFragment extends Fragment { diff --git a/src/de/blinkt/openvpn/FileSelect.java b/src/de/blinkt/openvpn/FileSelect.java new file mode 100644 index 0000000..3cc060c --- /dev/null +++ b/src/de/blinkt/openvpn/FileSelect.java @@ -0,0 +1,145 @@ +package de.blinkt.openvpn; + + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; + +import android.app.ActionBar; +import android.app.ActionBar.Tab; +import android.app.Activity; +import android.app.AlertDialog; +import android.app.AlertDialog.Builder; +import android.app.Fragment; +import android.app.FragmentTransaction; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; + +public class FileSelect extends Activity { + public static final String RESULT_DATA = "RESULT_PATH"; + public static final String START_DATA = "START_DATA"; + public static final String INLINE_TAG = "[[INLINE]]"; + private FileSelectionFragment mFSFragment; + private InlineFileTab mInlineFragment; + private String mData; + private Tab inlineFileTab; + private Tab fileExplorerTab; + + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.file_dialog); + + mData = getIntent().getStringExtra(START_DATA); + + ActionBar bar = getActionBar(); + bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + fileExplorerTab = bar.newTab().setText(R.string.file_explorer_tab); + inlineFileTab = bar.newTab().setText(R.string.inline_file_tab); + + mFSFragment = new FileSelectionFragment(); + mInlineFragment = new InlineFileTab(); + fileExplorerTab.setTabListener(new MyTabsListener<FileSelectionFragment>(this, mFSFragment)); + inlineFileTab.setTabListener(new MyTabsListener<InlineFileTab>(this, mInlineFragment)); + + bar.addTab(fileExplorerTab); + bar.addTab(inlineFileTab); + + + + } + + protected class MyTabsListener<T extends Fragment> implements ActionBar.TabListener + { + private Fragment mFragment; + private boolean mAdded=false; + + public MyTabsListener( Activity activity, Fragment fragment){ + this.mFragment = fragment; + } + + public void onTabSelected(Tab tab, FragmentTransaction ft) { + // Check if the fragment is already initialized + if (!mAdded) { + // If not, instantiate and add it to the activity + ft.add(android.R.id.content, mFragment); + mAdded =true; + } else { + // If it exists, simply attach it in order to show it + ft.attach(mFragment); + } + } + + @Override + public void onTabUnselected(Tab tab, FragmentTransaction ft) { + ft.detach(mFragment); + } + + @Override + public void onTabReselected(Tab tab, FragmentTransaction ft) { + + } + } + + public void importFile(String path) { + File ifile = new File(path); + Exception fe = null; + try { + FileInputStream fis = new FileInputStream(ifile); + String data =INLINE_TAG; + + byte buf[] =new byte[16384]; + int len=fis.read(buf); + while(len >0) { + data += new String(buf,0,len); + len=fis.read(buf); + } + + mData =data; + mInlineFragment.setData(data); + getActionBar().selectTab(inlineFileTab); + } catch (FileNotFoundException e) { + fe = e; + } catch (IOException e) { + fe =e; + } + if(fe!=null) { + Builder ab = new AlertDialog.Builder(this); + ab.setTitle(R.string.error_importing_file); + ab.setMessage(getString(R.string.import_error_message) + "\n" + fe.getLocalizedMessage()); + ab.setPositiveButton(android.R.string.ok, null); + ab.show(); + } + } + + public void setFile(String path) { + Intent intent = new Intent(); + intent.putExtra(RESULT_DATA, mData); + setResult(Activity.RESULT_OK,intent); + finish(); + } + + public String getSelectPath() { + if(mData.startsWith(INLINE_TAG)) + return mData; + else + return "/mnt/sdcard"; + } + + public CharSequence getInlineData() { + if(mData.startsWith(INLINE_TAG)) + return mData.substring(INLINE_TAG.length()); + else + return ""; + } + + public void saveInlineData(String string) { + Intent intent = new Intent(); + intent.putExtra(RESULT_DATA, mData); + setResult(Activity.RESULT_OK,intent); + finish(); + + } +} diff --git a/src/de/blinkt/openvpn/FileSelectLayout.java b/src/de/blinkt/openvpn/FileSelectLayout.java index 2eba951..bbaf777 100644 --- a/src/de/blinkt/openvpn/FileSelectLayout.java +++ b/src/de/blinkt/openvpn/FileSelectLayout.java @@ -11,12 +11,11 @@ import android.widget.Button; import android.widget.LinearLayout; import android.widget.TextView; -import com.lamerman.FileDialog; -import com.lamerman.SelectionMode; public class FileSelectLayout extends LinearLayout implements OnClickListener { - private TextView mData; + private TextView mDataView; + private String mData; private Fragment mFragment; private int mTaskId; private Button mSelectButton; @@ -32,7 +31,7 @@ public class FileSelectLayout extends LinearLayout implements OnClickListener { TextView tview = (TextView) findViewById(R.id.file_title); tview.setText(title); - mData = (TextView) findViewById(R.id.file_selected_item); + mDataView = (TextView) findViewById(R.id.file_selected_item); mSelectButton = (Button) findViewById(R.id.file_select_button); mSelectButton.setOnClickListener(this); @@ -45,20 +44,23 @@ public class FileSelectLayout extends LinearLayout implements OnClickListener { } public void getCertificateFileDialog() { - Intent startFC = new Intent(getContext(),FileDialog.class); - startFC.putExtra(FileDialog.START_PATH, "/sdcard"); - startFC.putExtra(FileDialog.SELECTION_MODE, SelectionMode.MODE_OPEN); + Intent startFC = new Intent(getContext(),FileSelect.class); + startFC.putExtra(FileSelect.START_DATA, mData); mFragment.startActivityForResult(startFC,mTaskId); } public String getData() { - return mData.getText().toString(); + return mData; } public void setData(String data) { - mData.setText(data); + mData = data; + if(mData.startsWith(FileSelect.INLINE_TAG)) + mDataView.setText(R.string.inline_file_data); + else + mDataView.setText(data); } diff --git a/src/de/blinkt/openvpn/FileSelectionFragment.java b/src/de/blinkt/openvpn/FileSelectionFragment.java new file mode 100644 index 0000000..3139028 --- /dev/null +++ b/src/de/blinkt/openvpn/FileSelectionFragment.java @@ -0,0 +1,244 @@ +package de.blinkt.openvpn; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.TreeMap; + +import android.app.AlertDialog; +import android.app.ListFragment; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ListView; +import android.widget.SimpleAdapter; +import android.widget.TextView; + +/** + * Activity para escolha de arquivos/diretorios. + * + * @author android + * + */ +public class FileSelectionFragment extends ListFragment { + + private static final String ITEM_KEY = "key"; + private static final String ITEM_IMAGE = "image"; + private static final String ROOT = "/"; + + + + + + private List<String> path = null; + private TextView myPath; + private ArrayList<HashMap<String, Object>> mList; + + private Button selectButton; + + + private String parentPath; + private String currentPath = ROOT; + + + private String[] formatFilter = null; + + private File selectedFile; + private HashMap<String, Integer> lastPositions = new HashMap<String, Integer>(); + private String mStartPath; + private Button importFile; + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.file_dialog_main, container,false); + + myPath = (TextView) v.findViewById(R.id.path); + + selectButton = (Button) v.findViewById(R.id.fdButtonSelect); + selectButton.setEnabled(false); + selectButton.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + if (selectedFile != null) { + ((FileSelect) getActivity()).setFile(selectedFile.getPath()); + + } + } + }); + + importFile = (Button) v.findViewById(R.id.importfile); + importFile.setEnabled(false); + importFile.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + ((FileSelect) getActivity()).importFile(selectedFile.getPath()); + } + }); + + + + + return v; + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + mStartPath = ((FileSelect) getActivity()).getSelectPath(); + getDir(mStartPath); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + private void getDir(String dirPath) { + + boolean useAutoSelection = dirPath.length() < currentPath.length(); + + Integer position = lastPositions.get(parentPath); + + getDirImpl(dirPath); + + if (position != null && useAutoSelection) { + getListView().setSelection(position); + } + + } + + /** + * Monta a estrutura de arquivos e diretorios filhos do diretorio fornecido. + * + * @param dirPath + * Diretorio pai. + */ + private void getDirImpl(final String dirPath) { + + currentPath = dirPath; + + final List<String> item = new ArrayList<String>(); + path = new ArrayList<String>(); + mList = new ArrayList<HashMap<String, Object>>(); + + File f = new File(currentPath); + File[] files = f.listFiles(); + if (files == null) { + currentPath = ROOT; + f = new File(currentPath); + files = f.listFiles(); + } + + myPath.setText(getText(R.string.location) + ": " + currentPath); + + if (!currentPath.equals(ROOT)) { + + item.add(ROOT); + addItem(ROOT, R.drawable.folder); + path.add(ROOT); + + item.add("../"); + addItem("../", R.drawable.folder); + path.add(f.getParent()); + parentPath = f.getParent(); + + } + + TreeMap<String, String> dirsMap = new TreeMap<String, String>(); + TreeMap<String, String> dirsPathMap = new TreeMap<String, String>(); + TreeMap<String, String> filesMap = new TreeMap<String, String>(); + TreeMap<String, String> filesPathMap = new TreeMap<String, String>(); + for (File file : files) { + if (file.isDirectory()) { + String dirName = file.getName(); + dirsMap.put(dirName, dirName); + dirsPathMap.put(dirName, file.getPath()); + } else { + final String fileName = file.getName(); + final String fileNameLwr = fileName.toLowerCase(); + // se ha um filtro de formatos, utiliza-o + if (formatFilter != null) { + boolean contains = false; + for (int i = 0; i < formatFilter.length; i++) { + final String formatLwr = formatFilter[i].toLowerCase(); + if (fileNameLwr.endsWith(formatLwr)) { + contains = true; + break; + } + } + if (contains) { + filesMap.put(fileName, fileName); + filesPathMap.put(fileName, file.getPath()); + } + // senao, adiciona todos os arquivos + } else { + filesMap.put(fileName, fileName); + filesPathMap.put(fileName, file.getPath()); + } + } + } + item.addAll(dirsMap.tailMap("").values()); + item.addAll(filesMap.tailMap("").values()); + path.addAll(dirsPathMap.tailMap("").values()); + path.addAll(filesPathMap.tailMap("").values()); + + SimpleAdapter fileList = new SimpleAdapter(getActivity(), mList, R.layout.file_dialog_row, new String[] { + ITEM_KEY, ITEM_IMAGE }, new int[] { R.id.fdrowtext, R.id.fdrowimage }); + + for (String dir : dirsMap.tailMap("").values()) { + addItem(dir, R.drawable.folder); + } + + for (String file : filesMap.tailMap("").values()) { + addItem(file, R.drawable.file); + } + + fileList.notifyDataSetChanged(); + + setListAdapter(fileList); + + } + + private void addItem(String fileName, int imageId) { + HashMap<String, Object> item = new HashMap<String, Object>(); + item.put(ITEM_KEY, fileName); + item.put(ITEM_IMAGE, imageId); + mList.add(item); + } + + + @Override + public void onListItemClick(ListView l, View v, int position, long id) { + + File file = new File(path.get(position)); + + if (file.isDirectory()) { + selectButton.setEnabled(false); + importFile.setEnabled(false); + + if (file.canRead()) { + lastPositions.put(currentPath, position); + getDir(path.get(position)); + } else { + new AlertDialog.Builder(getActivity()).setIcon(R.drawable.icon) + .setTitle("[" + file.getName() + "] " + getText(R.string.cant_read_folder)) + .setPositiveButton("OK", null).show(); + } + } else { + selectedFile = file; + v.setSelected(true); + selectButton.setEnabled(true); + importFile.setEnabled(true); + } + } + +} diff --git a/src/de/blinkt/openvpn/InlineFileTab.java b/src/de/blinkt/openvpn/InlineFileTab.java new file mode 100644 index 0000000..1104d29 --- /dev/null +++ b/src/de/blinkt/openvpn/InlineFileTab.java @@ -0,0 +1,65 @@ +package de.blinkt.openvpn; + +import android.app.Fragment; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.EditText; + +public class InlineFileTab extends Fragment +{ + + private static final int MENU_SAVE = 0; + private EditText mInlineData; + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + mInlineData.setText(((FileSelect)getActivity()).getInlineData()); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) + { + + View v = inflater.inflate(R.layout.file_dialog_inline, container, false); + mInlineData =(EditText) v.findViewById(R.id.inlineFileData); + return v; + } + + public void setData(String data) { + if(mInlineData!=null) + mInlineData.setText(data); + + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + menu.add(0, MENU_SAVE, 0, "Use inline data") + .setIcon(android.R.drawable.ic_menu_save) + .setAlphabeticShortcut('u') + .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM + | MenuItem.SHOW_AS_ACTION_WITH_TEXT); + } + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if(item.getItemId()==MENU_SAVE){ + ((FileSelect)getActivity()).saveInlineData(mInlineData.getText().toString()); + return true; + } + return super.onOptionsItemSelected(item); + } + +}
\ No newline at end of file diff --git a/src/de/blinkt/openvpn/LaunchVPN.java b/src/de/blinkt/openvpn/LaunchVPN.java index 8aeb996..c50a176 100644 --- a/src/de/blinkt/openvpn/LaunchVPN.java +++ b/src/de/blinkt/openvpn/LaunchVPN.java @@ -20,7 +20,6 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; import java.util.Collection; import java.util.Vector; diff --git a/src/de/blinkt/openvpn/OpenVPN.java b/src/de/blinkt/openvpn/OpenVPN.java index 58187df..71df887 100644 --- a/src/de/blinkt/openvpn/OpenVPN.java +++ b/src/de/blinkt/openvpn/OpenVPN.java @@ -3,8 +3,6 @@ package de.blinkt.openvpn; import java.util.LinkedList; import java.util.Vector; -import android.util.Log; - public class OpenVPN { private static OpenVpnService mOpenVpnService; private static final int MAXLOGENTRIES = 500; diff --git a/src/de/blinkt/openvpn/OpenVPNThread.java b/src/de/blinkt/openvpn/OpenVPNThread.java index 008598e..a24abb8 100644 --- a/src/de/blinkt/openvpn/OpenVPNThread.java +++ b/src/de/blinkt/openvpn/OpenVPNThread.java @@ -4,8 +4,6 @@ import java.io.BufferedReader; import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.io.Reader;
-import java.util.Arrays;
import java.util.LinkedList;
import android.util.Log;
diff --git a/src/de/blinkt/openvpn/OpenVpnService.java b/src/de/blinkt/openvpn/OpenVpnService.java index 9f0f732..9030d29 100644 --- a/src/de/blinkt/openvpn/OpenVpnService.java +++ b/src/de/blinkt/openvpn/OpenVpnService.java @@ -20,7 +20,6 @@ import java.io.IOException; import java.util.List; import java.util.Vector; -import android.R.anim; import android.app.ActivityManager; import android.app.ActivityManager.RunningAppProcessInfo; import android.app.PendingIntent; diff --git a/src/de/blinkt/openvpn/Settings_Authentication.java b/src/de/blinkt/openvpn/Settings_Authentication.java index 4124783..003a26d 100644 --- a/src/de/blinkt/openvpn/Settings_Authentication.java +++ b/src/de/blinkt/openvpn/Settings_Authentication.java @@ -12,8 +12,6 @@ import android.preference.Preference.OnPreferenceClickListener; import android.preference.PreferenceFragment; import android.preference.SwitchPreference; -import com.lamerman.FileDialog; -import com.lamerman.SelectionMode; public class Settings_Authentication extends PreferenceFragment implements OnPreferenceChangeListener, OnPreferenceClickListener { private static final int SELECT_TLS_FILE = 23223232; @@ -25,6 +23,7 @@ public class Settings_Authentication extends PreferenceFragment implements OnPre private Preference mTLSAuthFile; private SwitchPreference mUseTLSAuth; private EditTextPreference mCipher; + private String mTlsAuthFileData; @Override public void onCreate(Bundle savedInstanceState) { @@ -61,7 +60,8 @@ public class Settings_Authentication extends PreferenceFragment implements OnPre onPreferenceChange(mRemoteCN, mProfile.mRemoteCN); mUseTLSAuth.setChecked(mProfile.mUseTLSAuth); - mTLSAuthFile.setSummary(mProfile.mTLSAuthFilename); + mTlsAuthFileData= mProfile.mTLSAuthFilename; + setTlsAuthSummary(mTlsAuthFileData); mTLSAuthDirection.setValue(mProfile.mTLSAuthDirection); mCipher.setText(mProfile.mCipher); onPreferenceChange(mCipher, mProfile.mCipher); @@ -73,10 +73,7 @@ public class Settings_Authentication extends PreferenceFragment implements OnPre mProfile.mRemoteCN=mRemoteCN.getText(); mProfile.mUseTLSAuth = mUseTLSAuth.isChecked(); - if(mTLSAuthFile.getSummary()==null) - mProfile.mTLSAuthFilename=null; - else - mProfile.mTLSAuthFilename = mTLSAuthFile.getSummary().toString(); + mProfile.mTLSAuthFilename = mTlsAuthFileData; if(mTLSAuthDirection.getValue()==null) mProfile.mTLSAuthDirection=null; @@ -109,9 +106,8 @@ public class Settings_Authentication extends PreferenceFragment implements OnPre return true; } void startFileDialog() { - Intent startFC = new Intent(getActivity(),FileDialog.class); - startFC.putExtra(FileDialog.START_PATH, "/sdcard"); - startFC.putExtra(FileDialog.SELECTION_MODE, SelectionMode.MODE_OPEN); + Intent startFC = new Intent(getActivity(),FileSelectionFragment.class); + startFC.putExtra(FileSelect.START_DATA, "/sdcard"); startActivityForResult(startFC,SELECT_TLS_FILE); } @@ -126,9 +122,17 @@ public class Settings_Authentication extends PreferenceFragment implements OnPre public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(requestCode==SELECT_TLS_FILE && resultCode == Activity.RESULT_OK){ - String filepath = data.getStringExtra(FileDialog.RESULT_PATH); - mTLSAuthFile.setSummary(filepath); + String result = data.getStringExtra(FileSelect.RESULT_DATA); + mTlsAuthFileData=result; + setTlsAuthSummary(result); } } + + private void setTlsAuthSummary(String result) { + if(result.startsWith(FileSelect.INLINE_TAG)) + mTLSAuthFile.setSummary(R.string.inline_file_data); + else + mTLSAuthFile.setSummary(result); + } }
\ No newline at end of file diff --git a/src/de/blinkt/openvpn/Settings_Basic.java b/src/de/blinkt/openvpn/Settings_Basic.java index ad58a77..7586b27 100644 --- a/src/de/blinkt/openvpn/Settings_Basic.java +++ b/src/de/blinkt/openvpn/Settings_Basic.java @@ -18,6 +18,7 @@ package de.blinkt.openvpn; import java.util.HashMap; +import android.app.Activity; import android.app.Fragment; import android.content.Intent; import android.os.Bundle; @@ -37,7 +38,6 @@ import android.widget.Spinner; import android.widget.TextView; import android.widget.ToggleButton; -import com.lamerman.FileDialog; import de.blinkt.openvpn.R.id; @@ -142,10 +142,10 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On @Override public void onActivityResult(int request, int result, Intent data) { - if (request >= CHOOSE_FILE_OFFSET) { - String filepath = data.getStringExtra(FileDialog.RESULT_PATH); + if (result == Activity.RESULT_OK && request >= CHOOSE_FILE_OFFSET) { + String filedata = data.getStringExtra(FileSelect.RESULT_DATA); FileSelectLayout fsl = fileselects.get(request); - fsl.setData(filepath); + fsl.setData(filedata); } savePreferences(); } diff --git a/src/de/blinkt/openvpn/VpnProfile.java b/src/de/blinkt/openvpn/VpnProfile.java index 63d6876..b3ce6a4 100644 --- a/src/de/blinkt/openvpn/VpnProfile.java +++ b/src/de/blinkt/openvpn/VpnProfile.java @@ -19,8 +19,6 @@ import java.util.Vector; import android.content.Context; import android.content.Intent; -import android.os.Parcel; -import android.os.Parcelable; import android.security.KeyChain; import android.security.KeyChainException; @@ -185,24 +183,17 @@ public class VpnProfile implements Serializable{ cfg+="management-query-passwords\n"; case VpnProfile.TYPE_CERTIFICATES: // Ca - cfg+="ca "; - cfg+=openVpnEscape(mCaFilename); - cfg+="\n"; + cfg+=insertFileData("ca",mCaFilename); // Client Cert + Key - cfg+="key "; - cfg+=openVpnEscape(mClientKeyFilename); - cfg+="\n"; - cfg+="cert "; - cfg+=openVpnEscape(mClientCertFilename); - cfg+="\n"; + cfg+=insertFileData("key",mClientKeyFilename); + cfg+=insertFileData("cert",mClientCertFilename); + break; case VpnProfile.TYPE_USERPASS_PKCS12: cfg+="auth-user-pass\n"; case VpnProfile.TYPE_PKCS12: - cfg+="pkcs12 "; - cfg+=openVpnEscape(mPKCS12Filename); - cfg+="\n"; + cfg+=insertFileData("pkcs12",mPKCS12Filename); cfg+="management-query-passwords\n"; break; @@ -217,7 +208,7 @@ public class VpnProfile implements Serializable{ case VpnProfile.TYPE_USERPASS: cfg+="auth-user-pass\n"; cfg+="management-query-passwords\n"; - cfg+="ca " +openVpnEscape(mCaFilename) +"\n"; + cfg+=insertFileData("ca",mCaFilename); } if(mUseLzo) { @@ -226,12 +217,15 @@ public class VpnProfile implements Serializable{ if(mUseTLSAuth) { if(mAuthenticationType==TYPE_STATICKEYS) - cfg+="secret "; + cfg+=insertFileData("scecret",mTLSAuthFilename); else - cfg+="tls-auth "; - cfg+=openVpnEscape(mTLSAuthFilename); + cfg+=insertFileData("tls-auth",mTLSAuthFilename); cfg+=" "; - cfg+= mTLSAuthDirection; + + if(nonNull(mTLSAuthDirection)) { + cfg+= "key-direction "; + cfg+= mTLSAuthDirection; + } cfg+="\n"; } @@ -297,6 +291,16 @@ public class VpnProfile implements Serializable{ return cfg; } + //! Put inline data inline and other data as normal escaped filename + private String insertFileData(String cfgentry, String filedata) { + if(filedata.startsWith(FileSelect.INLINE_TAG)){ + String datawoheader = filedata.substring(FileSelect.INLINE_TAG.length()); + return String.format("<%s>\n%s\n</%s>\n",cfgentry,datawoheader,cfgentry); + } else { + return String.format("%s %s",cfgentry,openVpnEscape(filedata)); + } + } + private boolean nonNull(String val) { if(val == null || val.equals("")) return false; |