diff options
| -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 1103b673..61c5f585 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 00000000..8e07ce31 --- /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 00000000..61e39134 --- /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 c803522c..2f88ffb7 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 9073c0be..2b7c82f0 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 a5c6944a..00000000 --- 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 3c05dfa8..00000000 --- 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 8497330f..97ca6396 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 94fc9594..26979946 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 00000000..3cc060c6 --- /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 2eba9515..bbaf7778 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 00000000..31390280 --- /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 00000000..1104d290 --- /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 8aeb9960..c50a1767 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 58187df2..71df887f 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 008598e4..a24abb8b 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 9f0f7326..9030d29a 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 4124783b..003a26dd 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 ad58a778..7586b27d 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 63d6876e..b3ce6a47 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; | 
