diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/de/blinkt/openvpn/FileProvider.java | 206 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/LogWindow.java | 70 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/MainActivity.java | 14 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/OpenVPN.java | 58 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/OpenVPNThread.java | 21 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/OpenVpnManagementThread.java | 10 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/SendDumpActivity.java | 60 | 
7 files changed, 251 insertions, 188 deletions
| diff --git a/src/de/blinkt/openvpn/FileProvider.java b/src/de/blinkt/openvpn/FileProvider.java index 1147ccf0..e86b544f 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 3c0f7246..790e143a 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 9b329817..32cf575b 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 48623865..0ae681bc 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 13b8688b..7d58552a 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 d15e6a33..9926ba13 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 00000000..8a09b535 --- /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; +	} +} | 
