0
0
mirror of https://github.com/schwabe/ics-openvpn.git synced 2024-09-20 03:52:27 +02:00

Rework FIle selection dialog.

Include possibility to include file content in VPN Profile. Allows safer storage of Certifcates and keys. (closes issue #13)

--HG--
rename : src/com/lamerman/FileDialog.java => src/de/blinkt/openvpn/FileSelectionFragment.java
This commit is contained in:
Arne Schwabe 2012-05-11 00:46:33 +02:00
parent be5159289c
commit bfb51aa744
20 changed files with 598 additions and 508 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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">
<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:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_alignParentBottom="true">
<LinearLayout
android:id="@+id/fdLinearLayoutList"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal" >
<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">
<Button
android:id="@+id/importfile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/import_file" >
</Button>
<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>
<Button
android:id="@+id/fdButtonSelect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/select" >
</Button>
</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:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="@+id/fdLinearLayoutList"
android:orientation="vertical" >
<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>
<TextView
android:id="@+id/path"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<ListView
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<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>
<TextView
android:id="@android:id/empty"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="@string/no_data" />
</LinearLayout>
</RelativeLayout>
</RelativeLayout>

View File

@ -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>

View File

@ -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);
}
}

View File

@ -1,7 +0,0 @@
package com.lamerman;
public class SelectionMode {
public static final int MODE_CREATE = 0;
public static final int MODE_OPEN = 1;
}

View File

@ -11,7 +11,7 @@ import java.util.Vector;
// And rember, this is valid :)
// --<foo>
// bar
// </bar>
// </foo>
public class ConfigParser {

View File

@ -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 {

View File

@ -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();
}
}

View File

@ -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);
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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();
}

View File

@ -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;