summaryrefslogtreecommitdiff
path: root/src/de/blinkt/openvpn
diff options
context:
space:
mode:
Diffstat (limited to 'src/de/blinkt/openvpn')
-rw-r--r--src/de/blinkt/openvpn/FileProvider.java206
-rw-r--r--src/de/blinkt/openvpn/LogWindow.java70
-rw-r--r--src/de/blinkt/openvpn/MainActivity.java14
-rw-r--r--src/de/blinkt/openvpn/OpenVPN.java58
-rw-r--r--src/de/blinkt/openvpn/OpenVPNThread.java21
-rw-r--r--src/de/blinkt/openvpn/OpenVpnManagementThread.java10
-rw-r--r--src/de/blinkt/openvpn/SendDumpActivity.java60
7 files changed, 251 insertions, 188 deletions
diff --git a/src/de/blinkt/openvpn/FileProvider.java b/src/de/blinkt/openvpn/FileProvider.java
index 1147ccf..e86b544 100644
--- a/src/de/blinkt/openvpn/FileProvider.java
+++ b/src/de/blinkt/openvpn/FileProvider.java
@@ -24,13 +24,15 @@ import java.io.IOException;
import java.io.InputStream;
import android.content.ContentProvider;
-import android.content.ContentValues;
import android.content.ContentProvider.PipeDataWriter;
+import android.content.ContentValues;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
+import android.database.MatrixCursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
+import android.provider.OpenableColumns;
import android.util.Log;
/**
@@ -38,92 +40,118 @@ import android.util.Log;
* our .apk.
*/
public class FileProvider extends ContentProvider
- implements PipeDataWriter<InputStream> {
- @Override
- public boolean onCreate() {
- return true;
- }
-
- @Override
- public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
- String sortOrder) {
- // Don't support queries.
- return null;
- }
-
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- // Don't support inserts.
- return null;
- }
-
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- // Don't support deletes.
- return 0;
- }
-
- @Override
- public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
- // Don't support updates.
- return 0;
- }
-
- @Override
- public String getType(Uri uri) {
- // For this sample, assume all files are .apks.
- return "application/octet-stream";
- }
-
- @Override
- public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException {
- // Try to open an asset with the given name.
- String path = uri.getPath();
- if(path.startsWith("/"))
- path = path.replaceFirst("/", "");
-
- // I think this already random enough, no need for magic secure cookies
- // 1f9563a4-a1f5-2165-255f2219-111823ef.dmp
- if (!path.matches("^[0-9a-z-.]*$"))
- throw new FileNotFoundException("url not in expect format " + uri);
-
- try {
-
- File cachedir = getContext().getCacheDir();
- File dumpfile = new File(cachedir,path);
- InputStream is = new FileInputStream(dumpfile);
- // Start a new thread that pipes the stream data back to the caller.
- return new AssetFileDescriptor(
- openPipeHelper(uri, null, null, is, this), 0,
- dumpfile.length());
- } catch (IOException e) {
- FileNotFoundException fnf = new FileNotFoundException("Unable to open minidump " + uri);
- throw fnf;
- }
- }
-
- @Override
- public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String mimeType,
- Bundle opts, InputStream args) {
- // Transfer data from the asset to the pipe the client is reading.
- byte[] buffer = new byte[8192];
- int n;
- FileOutputStream fout = new FileOutputStream(output.getFileDescriptor());
- try {
- while ((n=args.read(buffer)) >= 0) {
- fout.write(buffer, 0, n);
- }
- } catch (IOException e) {
- Log.i("OpenVPNFileProvider", "Failed transferring", e);
- } finally {
- try {
- args.close();
- } catch (IOException e) {
- }
- try {
- fout.close();
- } catch (IOException e) {
- }
- }
- }
+implements PipeDataWriter<InputStream> {
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ try {
+ File dumpfile = getFileFromURI(uri);
+
+
+ MatrixCursor c = new MatrixCursor(projection);
+
+ Object[] row = new Object[projection.length];
+ int i=0;
+ for (String r:projection) {
+ if(r.equals(OpenableColumns.SIZE))
+ row[i] = dumpfile.length();
+ if(r.equals(OpenableColumns.DISPLAY_NAME))
+ row[i] = dumpfile.getName();
+ i++;
+ }
+ c.addRow(row);
+ return c;
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ return null;
+ }
+
+
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ // Don't support inserts.
+ return null;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ // Don't support deletes.
+ return 0;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ // Don't support updates.
+ return 0;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ // For this sample, assume all files are .apks.
+ return "application/octet-stream";
+ }
+
+ @Override
+ public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException {
+ File dumpfile = getFileFromURI(uri);
+
+ try {
+
+ InputStream is = new FileInputStream(dumpfile);
+ // Start a new thread that pipes the stream data back to the caller.
+ return new AssetFileDescriptor(
+ openPipeHelper(uri, null, null, is, this), 0,
+ dumpfile.length());
+ } catch (IOException e) {
+ FileNotFoundException fnf = new FileNotFoundException("Unable to open minidump " + uri);
+ throw fnf;
+ }
+ }
+
+ private File getFileFromURI(Uri uri) throws FileNotFoundException {
+ // Try to open an asset with the given name.
+ String path = uri.getPath();
+ if(path.startsWith("/"))
+ path = path.replaceFirst("/", "");
+
+ // I think this already random enough, no need for magic secure cookies
+ // 1f9563a4-a1f5-2165-255f2219-111823ef.dmp
+ if (!path.matches("^[0-9a-z-.]*(dmp|dmp.log)$"))
+ throw new FileNotFoundException("url not in expect format " + uri);
+ File cachedir = getContext().getCacheDir();
+ File dumpfile = new File(cachedir,path);
+ return dumpfile;
+ }
+
+ @Override
+ public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String mimeType,
+ Bundle opts, InputStream args) {
+ // Transfer data from the asset to the pipe the client is reading.
+ byte[] buffer = new byte[8192];
+ int n;
+ FileOutputStream fout = new FileOutputStream(output.getFileDescriptor());
+ try {
+ while ((n=args.read(buffer)) >= 0) {
+ fout.write(buffer, 0, n);
+ }
+ } catch (IOException e) {
+ Log.i("OpenVPNFileProvider", "Failed transferring", e);
+ } finally {
+ try {
+ args.close();
+ } catch (IOException e) {
+ }
+ try {
+ fout.close();
+ } catch (IOException e) {
+ }
+ }
+ }
}
diff --git a/src/de/blinkt/openvpn/LogWindow.java b/src/de/blinkt/openvpn/LogWindow.java
index 3c0f724..790e143 100644
--- a/src/de/blinkt/openvpn/LogWindow.java
+++ b/src/de/blinkt/openvpn/LogWindow.java
@@ -1,9 +1,5 @@
package de.blinkt.openvpn;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.ArrayList;
import java.util.Vector;
import android.app.AlertDialog;
@@ -16,7 +12,6 @@ import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.database.DataSetObserver;
-import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler.Callback;
@@ -227,8 +222,6 @@ public class LogWindow extends ListActivity implements StateListener {
} else if(item.getItemId()==R.id.info) {
if(mBconfig==null)
OpenVPN.triggerLogBuilderConfig();
- } else if(item.getItemId()==R.id.minidump) {
- emailMiniDumps();
} else if(item.getItemId()==R.id.send) {
ladapter.shareLog();
@@ -258,72 +251,9 @@ public class LogWindow extends ListActivity implements StateListener {
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.logmenu, menu);
-
-
-
- if(getLastestDump()==null)
- menu.removeItem(R.id.minidump);
-
return true;
}
- private File getLastestDump() {
- long newestDumpTime=0;
- File newestDumpFile=null;
-
- for(File f:getCacheDir().listFiles()) {
- if(!f.getName().endsWith(".dmp"))
- continue;
-
- if (newestDumpTime < f.lastModified()) {
- newestDumpTime = f.lastModified();
- newestDumpFile=f;
- }
- }
- return newestDumpFile;
- }
-
-
- public void emailMiniDumps()
- {
- //need to "send multiple" to get more than one attachment
- final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND_MULTIPLE);
- emailIntent.setType("*/*");
- emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,
- new String[]{"Arne Schwabe <arne@rfc2549.org>"});
- emailIntent.putExtra(Intent.EXTRA_SUBJECT, "OpenVPN Minidump");
-
-
- ArrayList<CharSequence> textarraylist = new ArrayList<CharSequence>();
- textarraylist.add("Please describe the issue you have experienced");
- emailIntent.putExtra(Intent.EXTRA_TEXT, textarraylist);
-
-
- ArrayList<Uri> uris = new ArrayList<Uri>();
-
- File ldump = getLastestDump();
- if(ldump==null) {
- OpenVPN.logError("No Minidump found!");
- }
-
- uris.add(Uri.parse("content://de.blinkt.openvpn.FileProvider/" + ldump.getName()));
- uris.add(Uri.parse("content://de.blinkt.openvpn.FileProvider/openvpn.log"));
-
-
- try {
- FileWriter logout = new FileWriter(new File(getCacheDir(),"openvpn.log"));
- logout.write(ladapter.getLogStr());
- logout.close();
-
- } catch (IOException e1) {
- OpenVPN.logError("Error writing log: " + e1.getLocalizedMessage());
- }
-
- //emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
- startActivity(emailIntent);
- }
-
@Override
protected void onResume() {
diff --git a/src/de/blinkt/openvpn/MainActivity.java b/src/de/blinkt/openvpn/MainActivity.java
index 9b32981..32cf575 100644
--- a/src/de/blinkt/openvpn/MainActivity.java
+++ b/src/de/blinkt/openvpn/MainActivity.java
@@ -1,8 +1,11 @@
package de.blinkt.openvpn;
+import java.io.File;
+import java.util.ArrayList;
import java.util.List;
import android.content.Intent;
+import android.net.Uri;
import android.preference.PreferenceActivity;
public class MainActivity extends PreferenceActivity {
@@ -19,6 +22,15 @@ public class MainActivity extends PreferenceActivity {
translation.summary = translatedby;
target.add(translation);
}
+
+ if(SendDumpActivity.getLastestDump(this)!=null) {
+ Header sendDump = new Header();
+ sendDump.titleRes = R.string.send_minidump;
+ sendDump.summaryRes = R.string.send_minidump_summary;
+ sendDump.intent = new Intent(this,SendDumpActivity.class);
+ target.add(sendDump);
+ }
+
}
@Override
@@ -29,4 +41,6 @@ public class MainActivity extends PreferenceActivity {
}
+
+
}
diff --git a/src/de/blinkt/openvpn/OpenVPN.java b/src/de/blinkt/openvpn/OpenVPN.java
index 4862386..0ae681b 100644
--- a/src/de/blinkt/openvpn/OpenVPN.java
+++ b/src/de/blinkt/openvpn/OpenVPN.java
@@ -7,10 +7,10 @@ import android.content.Context;
import android.os.Build;
public class OpenVPN {
-
+
public static LinkedList<LogItem> logbuffer;
-
+
private static Vector<LogListener> logListener;
private static Vector<StateListener> stateListener;
private static String[] mBconfig;
@@ -18,14 +18,14 @@ public class OpenVPN {
private static String mLaststatemsg;
private static String mLaststate;
-
+
static {
logbuffer = new LinkedList<LogItem>();
logListener = new Vector<OpenVPN.LogListener>();
stateListener = new Vector<OpenVPN.StateListener>();
logInformation();
}
-
+
static class LogItem {
public static final int ERROR = 1;
public static final int INFO = 2;
@@ -36,20 +36,20 @@ public class OpenVPN {
private int mRessourceId;
// Default log priority
int mLevel = INFO;
-
+
public LogItem(int ressourceId, Object[] args) {
- mRessourceId = ressourceId;
- mArgs = args;
+ mRessourceId = ressourceId;
+ mArgs = args;
}
-
+
public LogItem(int loglevel,int ressourceId, Object[] args) {
- mRessourceId = ressourceId;
- mArgs = args;
- mLevel = loglevel;
- }
+ mRessourceId = ressourceId;
+ mArgs = args;
+ mLevel = loglevel;
+ }
+
-
public LogItem(String message) {
mMessage = message;
}
@@ -70,28 +70,32 @@ public class OpenVPN {
if(mMessage !=null) {
return mMessage;
} else {
- if(mArgs == null)
- return c.getString(mRessourceId);
- else
- return c.getString(mRessourceId,mArgs);
+ if(c!=null) {
+ if(mArgs == null)
+ return c.getString(mRessourceId);
+ else
+ return c.getString(mRessourceId,mArgs);
+ } else {
+ return String.format("Log (no context) resid %d", mRessourceId);
+ }
}
}
}
-
+
private static final int MAXLOGENTRIES = 200;
public static final String MANAGMENT_PREFIX = "M:";
-
+
public interface LogListener {
void newLog(LogItem logItem);
}
-
+
public interface StateListener {
void updateState(String state, String logmessage);
}
@@ -108,7 +112,7 @@ public class OpenVPN {
}
private static void logInformation() {
-
+
logInfo(R.string.mobile_info,Build.MODEL, Build.BOARD,Build.BRAND,Build.VERSION.SDK_INT);
}
@@ -120,7 +124,7 @@ public class OpenVPN {
logListener.remove(ll);
}
-
+
synchronized static void addStateListener(StateListener sl){
stateListener.add(sl);
if(mLaststate!=null)
@@ -156,7 +160,7 @@ public class OpenVPN {
public synchronized static void updateStateString(String state, String msg) {
mLaststate= state;
mLaststatemsg = msg;
-
+
for (StateListener sl : stateListener) {
sl.updateState(state,msg);
}
@@ -174,7 +178,7 @@ public class OpenVPN {
logbuffer.addLast(logItem);
if(logbuffer.size()>MAXLOGENTRIES)
logbuffer.removeFirst();
-
+
for (LogListener ll : logListener) {
ll.newLog(logItem);
}
@@ -182,7 +186,7 @@ public class OpenVPN {
public static void logError(String msg) {
newlogItem(new LogItem(LogItem.ERROR, msg));
-
+
}
public static void logError(int ressourceId) {
@@ -191,6 +195,6 @@ public class OpenVPN {
public static void logError(int ressourceId, Object... args) {
newlogItem(new LogItem(LogItem.ERROR, ressourceId,args));
}
-
-
+
+
}
diff --git a/src/de/blinkt/openvpn/OpenVPNThread.java b/src/de/blinkt/openvpn/OpenVPNThread.java
index 13b8688..7d58552 100644
--- a/src/de/blinkt/openvpn/OpenVPNThread.java
+++ b/src/de/blinkt/openvpn/OpenVPNThread.java
@@ -1,19 +1,24 @@
package de.blinkt.openvpn;
import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.LinkedList;
import android.util.Log;
+import de.blinkt.openvpn.OpenVPN.LogItem;
public class OpenVPNThread implements Runnable {
+ private static final String DUMP_PATH_STRING = "Dump path: ";
private static final String TAG = "OpenVPN";
private String[] mArgv;
private Process mProcess;
private String mNativeDir;
private OpenVpnService mService;
+ private String mDumpPath;
public OpenVPNThread(OpenVpnService service,String[] argv, String nativelibdir)
{
@@ -49,7 +54,18 @@ public class OpenVPNThread implements Runnable {
OpenVPN.logError("Process exited with exit value " + exitvalue);
OpenVPN.updateStateString("NOPROCESS","No process running.");
-
+ if(mDumpPath!=null) {
+ try {
+ BufferedWriter logout = new BufferedWriter(new FileWriter(mDumpPath + ".log"));
+ for(LogItem li :OpenVPN.getlogbuffer()){
+ logout.write(li.getString(null) + "\n");
+ }
+ logout.close();
+ OpenVPN.logError(R.string.minidump_generated);
+ } catch (IOException e) {
+ OpenVPN.logError("Writing minidump log: " +e.getLocalizedMessage());
+ }
+ }
mService.processDied();
Log.i(TAG, "Exiting");
@@ -89,6 +105,9 @@ public class OpenVPNThread implements Runnable {
while(true) {
String logline = br.readLine();
+ if (logline.startsWith(DUMP_PATH_STRING))
+ mDumpPath = logline.substring(DUMP_PATH_STRING.length());
+
if(logline==null) {
return;
}
diff --git a/src/de/blinkt/openvpn/OpenVpnManagementThread.java b/src/de/blinkt/openvpn/OpenVpnManagementThread.java
index d15e6a3..9926ba1 100644
--- a/src/de/blinkt/openvpn/OpenVpnManagementThread.java
+++ b/src/de/blinkt/openvpn/OpenVpnManagementThread.java
@@ -39,7 +39,8 @@ public class OpenVpnManagementThread implements Runnable {
private long mLastOut=0;
private LocalServerSocket mServerSocket;
private boolean mReleaseHold=true;
- private boolean mWaitingForRelease=false;
+ private boolean mWaitingForRelease=false;
+ private long mLastHoldRelease=0;
private static Vector<OpenVpnManagementThread> active=new Vector<OpenVpnManagementThread>();
@@ -223,8 +224,15 @@ public class OpenVpnManagementThread implements Runnable {
}
}
private void releaseHoldCmd() {
+ if ((System.currentTimeMillis()- mLastHoldRelease) < 5000) {
+ try {
+ Thread.sleep(3000);
+ } catch (InterruptedException e) {}
+
+ }
mWaitingForRelease=false;
mReleaseHold=true;
+ mLastHoldRelease = System.currentTimeMillis();
managmentCommand("hold release\n");
managmentCommand("bytecount " + mBytecountinterval + "\n");
managmentCommand("state on\n");
diff --git a/src/de/blinkt/openvpn/SendDumpActivity.java b/src/de/blinkt/openvpn/SendDumpActivity.java
new file mode 100644
index 0000000..8a09b53
--- /dev/null
+++ b/src/de/blinkt/openvpn/SendDumpActivity.java
@@ -0,0 +1,60 @@
+package de.blinkt.openvpn;
+
+import java.io.File;
+import java.util.ArrayList;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+
+public class SendDumpActivity extends Activity {
+
+ protected void onStart() {
+ super.onStart();
+ emailMiniDumps();
+ finish();
+ };
+
+ public void emailMiniDumps()
+ {
+ //need to "send multiple" to get more than one attachment
+ final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND_MULTIPLE);
+ emailIntent.setType("*/*");
+ emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,
+ new String[]{"Arne Schwabe <arne@rfc2549.org>"});
+ emailIntent.putExtra(Intent.EXTRA_SUBJECT, "OpenVPN Minidump");
+
+ emailIntent.putExtra(Intent.EXTRA_TEXT, "Please describe the issue you have experienced");
+
+ ArrayList<Uri> uris = new ArrayList<Uri>();
+
+ File ldump = getLastestDump(this);
+ if(ldump==null) {
+ OpenVPN.logError("No Minidump found!");
+ }
+
+ uris.add(Uri.parse("content://de.blinkt.openvpn.FileProvider/" + ldump.getName()));
+ uris.add(Uri.parse("content://de.blinkt.openvpn.FileProvider/" + ldump.getName() + ".log"));
+
+ emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
+ startActivity(emailIntent);
+ }
+
+ static public File getLastestDump(Context c) {
+ long newestDumpTime=0;
+ File newestDumpFile=null;
+
+ for(File f:c.getCacheDir().listFiles()) {
+ if(!f.getName().endsWith(".dmp"))
+ continue;
+
+ if (newestDumpTime < f.lastModified()) {
+ newestDumpTime = f.lastModified();
+ newestDumpFile=f;
+ }
+ }
+ return newestDumpFile;
+ }
+}