~xdavidwu/saf-sftp

7f3e1680cff660e988387bfe0fbfc8d1705935a2 — xdavidwu 2 years ago d3f7db3
reformat code
M src/main/java/org/safsftp/MainActivity.java => src/main/java/org/safsftp/MainActivity.java +49 -49
@@ 8,28 8,26 @@ import android.preference.PreferenceActivity;
import android.provider.DocumentsContract;
import android.os.Bundle;

public class MainActivity extends PreferenceActivity
	implements OnSharedPreferenceChangeListener {
	private EditTextPreference hostText, portText, usernameText, passwdText,
		mountpointText;
public class MainActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {
	private EditTextPreference hostText, portText, usernameText, passwdText, mountpointText;

	private void notifyRootChanges(){
		Uri uri=DocumentsContract.buildRootsUri("org.safsftp");
		getContentResolver().notifyChange(uri,null);
	private void notifyRootChanges() {
		Uri uri = DocumentsContract.buildRootsUri("org.safsftp");
		getContentResolver().notifyChange(uri, null);
	}
	

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		addPreferencesFromResource(R.xml.main_pre);

		hostText=(EditTextPreference)findPreference("host");
		portText=(EditTextPreference)findPreference("port");
		usernameText=(EditTextPreference)findPreference("username");
		passwdText=(EditTextPreference)findPreference("passwd");
		mountpointText=(EditTextPreference)findPreference("mountpoint");
		hostText = (EditTextPreference) findPreference("host");
		portText = (EditTextPreference) findPreference("port");
		usernameText = (EditTextPreference) findPreference("username");
		passwdText = (EditTextPreference) findPreference("passwd");
		mountpointText = (EditTextPreference) findPreference("mountpoint");

		SharedPreferences settings=getPreferenceScreen().getSharedPreferences();
		SharedPreferences settings = getPreferenceScreen().getSharedPreferences();
		settings.registerOnSharedPreferenceChangeListener(this);
		if (!settings.getString("host", "").equals(""))
			hostText.setSummary(settings.getString("host", ""));


@@ 40,44 38,46 @@ public class MainActivity extends PreferenceActivity
		if (!settings.getString("passwd", "").equals(""))
			passwdText.setSummary(getString(R.string.passwd_filled));
		if (!settings.getString("mountpoint", "").equals(""))
			mountpointText.setSummary(settings.getString("mountpoint",""));
}
			mountpointText.setSummary(settings.getString("mountpoint", ""));
	}

	@Override
	public void onSharedPreferenceChanged(SharedPreferences settings,
			String key) {
	public void onSharedPreferenceChanged(SharedPreferences settings, String key) {
		notifyRootChanges();
		switch(key){
		case "host":
			if (settings.getString("host", "").equals(""))
				hostText.setSummary(getString(R.string.host_summary));
			else
				hostText.setSummary(settings.getString("host", ""));
			break;
		case "port":
			if (settings.getString("port", "").equals(""))
				portText.setSummary(getString(R.string.port_summary));
			else
				portText.setSummary(settings.getString("port", ""));
			break;
		case "username":
			if (settings.getString("username", "").equals(""))
				usernameText.setSummary(getString(R.string.username_summary));
			else
				usernameText.setSummary(settings.getString("username", ""));
			break;
		case "passwd":
			if (settings.getString("passwd", "").equals(""))
				passwdText.setSummary(getString(R.string.passwd_summary));
			else
				passwdText.setSummary(getString(R.string.passwd_filled));
			break;
		case "mountpoint":
			if (settings.getString("mountpoint", "").equals(""))
				mountpointText.setSummary(getString(R.string.mountpoint_summary));
			else
				mountpointText.setSummary(settings.getString("mountpoint",""));
			break;
		switch (key) {
			case "host":
				if (settings.getString("host", "").equals(""))
					hostText.setSummary(getString(R.string.host_summary));
				else
					hostText.setSummary(settings.getString("host", ""));
				break;
			case "port":
				if (settings.getString("port", "").equals(""))
					portText.setSummary(getString(R.string.port_summary));
				else
					portText.setSummary(settings.getString("port", ""));
				break;
			case "username":
				if (settings.getString("username", "").equals(""))
					usernameText.setSummary(
						getString(R.string.username_summary));
				else
					usernameText.setSummary(settings.getString("username", ""));
				break;
			case "passwd":
				if (settings.getString("passwd", "").equals(""))
					passwdText.setSummary(getString(R.string.passwd_summary));
				else
					passwdText.setSummary(getString(R.string.passwd_filled));
				break;
			case "mountpoint":
				if (settings.getString("mountpoint", "").equals(""))
					mountpointText.setSummary(
						getString(R.string.mountpoint_summary));
				else
					mountpointText.setSummary(
						settings.getString("mountpoint", ""));
				break;
		}
	}
}

M src/main/java/org/safsftp/SFTPDocumentsProvider.java => src/main/java/org/safsftp/SFTPDocumentsProvider.java +110 -109
@@ 32,12 32,12 @@ import java.util.Vector;

public class SFTPDocumentsProvider extends DocumentsProvider {
	private Connection connection;
	private String host=null,port=null; //TODO: multiple server support
	private String host = null, port = null; // TODO: multiple server support
	private StorageManager sm;
	private Handler ioHandler;
	private ToastThread lthread;
	
	private static final String[] DEFAULT_ROOT_PROJECTION=new String[]{

	private static final String[] DEFAULT_ROOT_PROJECTION = new String[] {
		Root.COLUMN_ROOT_ID,
		Root.COLUMN_FLAGS,
		Root.COLUMN_ICON,


@@ 45,21 45,19 @@ public class SFTPDocumentsProvider extends DocumentsProvider {
		Root.COLUMN_DOCUMENT_ID,
	};

	private static final String[] DEFAULT_DOC_PROJECTION=new String[]{
	private static final String[] DEFAULT_DOC_PROJECTION = new String[] {
		Document.COLUMN_DOCUMENT_ID,
		Document.COLUMN_DISPLAY_NAME,
		Document.COLUMN_MIME_TYPE,
		Document.COLUMN_LAST_MODIFIED,
		Document.COLUMN_SIZE
		Document.COLUMN_SIZE,
	};

	private static String getMime(String filename) {
		int idx = filename.lastIndexOf(".");
		if(idx > 0){
			String mime = MimeTypeMap.getSingleton()
				.getMimeTypeFromExtension(filename
					.substring(idx + 1)
					.toLowerCase(Locale.ROOT));
		if (idx > 0) {
			String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
				filename.substring(idx + 1).toLowerCase(Locale.ROOT));
			if (mime != null) {
				return mime;
			}


@@ 71,49 69,46 @@ public class SFTPDocumentsProvider extends DocumentsProvider {
		try {
			connection.ping();
			return new SFTPv3Client(connection);
		} catch (Exception e) {
		}
		catch(Exception e){
		}
		SharedPreferences settings=PreferenceManager
			.getDefaultSharedPreferences(getContext());
		if(host==null||port==null){
			host=settings.getString("host","");
			port=settings.getString("port","22");
		SharedPreferences settings =
			PreferenceManager.getDefaultSharedPreferences(getContext());
		if (host == null || port == null) {
			host = settings.getString("host", "");
			port = settings.getString("port", "22");
		}
		Log.v("SFTP","connect "+host+":"+port);
		Log.v("SFTP", "connect " + host + ":" + port);
		try {
			connection=new Connection(host,Integer.parseInt(port));
			connection.connect(null,10000,10000);
			if(!connection.authenticateWithPassword(settings.getString("username",""),
				settings.getString("passwd",""))){
				Message msg=lthread.handler.obtainMessage();
				msg.obj="SFTP auth failed.";
			connection = new Connection(host, Integer.parseInt(port));
			connection.connect(null, 10000, 10000);
			if (!connection.authenticateWithPassword(settings.getString("username", ""),
				    settings.getString("passwd", ""))) {
				Message msg = lthread.handler.obtainMessage();
				msg.obj = "SFTP auth failed.";
				lthread.handler.sendMessage(msg);
			}
			return new SFTPv3Client(connection);
		}
		catch(Exception e){
			Log.e("SFTP","connect "+e.toString());
			Message msg=lthread.handler.obtainMessage();
			msg.obj=e.toString();
		} catch (Exception e) {
			Log.e("SFTP", "connect " + e.toString());
			Message msg = lthread.handler.obtainMessage();
			msg.obj = e.toString();
			lthread.handler.sendMessage(msg);
			connection.close();
		}
		return null;
	}

	private void editPolicyIfMainThread(){
		//FIXME
		//if(Looper.getMainLooper()==Looper.myLooper()){
	private void editPolicyIfMainThread() {
		// FIXME
		// if(Looper.getMainLooper()==Looper.myLooper()){
		//	Log.w("SFTP","We're on main thread.");
			StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.LAX);
		StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.LAX);
		//}
	}

	@Override
	public boolean onCreate() {
		sm = (StorageManager) getContext()
			.getSystemService(Context.STORAGE_SERVICE);
		sm = (StorageManager) getContext().getSystemService(Context.STORAGE_SERVICE);
		lthread = new ToastThread(getContext());
		lthread.start();
		HandlerThread ioThread = new HandlerThread("IO thread");


@@ 122,66 117,70 @@ public class SFTPDocumentsProvider extends DocumentsProvider {
		return true;
	}

	public ParcelFileDescriptor openDocument(String documentId,
			String mode,CancellationSignal cancellationSignal) {
	public ParcelFileDescriptor openDocument(
		String documentId, String mode, CancellationSignal cancellationSignal) {
		if (!"r".equals(mode)) {
			throw new UnsupportedOperationException("Mode "+mode+" is not supported yet.");
			throw new UnsupportedOperationException(
				"Mode " + mode + " is not supported yet.");
		}
		editPolicyIfMainThread();
		SFTPv3Client sftp;
		if((sftp=retriveConnection())==null){
			//TODO notify error
		if ((sftp = retriveConnection()) == null) {
			// TODO notify error
			return null;
		}
		String filename=documentId.substring(documentId.indexOf("/")+1);
		Log.v("SFTP","od "+documentId+" on "+host+":"+port);
		String filename = documentId.substring(documentId.indexOf("/") + 1);
		Log.v("SFTP", "od " + documentId + " on " + host + ":" + port);
		SFTPv3FileHandle file;
		try {
			file = sftp.openFileRO(filename);
			return sm.openProxyFileDescriptor(
				ParcelFileDescriptor.MODE_READ_ONLY,
				new SFTPProxyFileDescriptorCallback(sftp, file),
				ioHandler);
			return sm.openProxyFileDescriptor(ParcelFileDescriptor.MODE_READ_ONLY,
				new SFTPProxyFileDescriptorCallback(sftp, file), ioHandler);
		} catch (IOException e) {
			//TODO notify error
			Log.e("SFTP","read file "+filename+" init "+e.toString());
			// TODO notify error
			Log.e("SFTP", "read file " + filename + " init " + e.toString());
			return null;
		}
	}

	public Cursor queryChildDocuments(String parentDocumentId,
			String[] projection,String sortOrder) {
		MatrixCursor result=new MatrixCursor(projection!=null?projection:DEFAULT_DOC_PROJECTION);
		Log.v("SFTP","qcf "+parentDocumentId+" on "+host+":"+port);
	public Cursor queryChildDocuments(
		String parentDocumentId, String[] projection, String sortOrder) {
		MatrixCursor result =
			new MatrixCursor(projection != null ? projection : DEFAULT_DOC_PROJECTION);
		Log.v("SFTP", "qcf " + parentDocumentId + " on " + host + ":" + port);
		editPolicyIfMainThread();
		SFTPv3Client sftp;
		if((sftp=retriveConnection())==null){
			//TODO notify error
		if ((sftp = retriveConnection()) == null) {
			// TODO notify error
			return result;
		}
		String filename=parentDocumentId.substring(parentDocumentId.indexOf("/")+1);
		try{
			Vector<SFTPv3DirectoryEntry> res=sftp.ls(filename);
			for(SFTPv3DirectoryEntry entry : res){
				Log.v("SFTP","qcf "+parentDocumentId+" "+entry.filename+" "+entry.attributes.size+" "+entry.attributes.mtime);
				if(entry.filename.equals(".")||entry.filename.equals(".."))continue;
				MatrixCursor.RowBuilder row=result.newRow();
				row.add(Document.COLUMN_DOCUMENT_ID,parentDocumentId+'/'+entry.filename);
				row.add(Document.COLUMN_DISPLAY_NAME,entry.filename);
				if(entry.attributes.isDirectory()){
					row.add(Document.COLUMN_MIME_TYPE,Document.MIME_TYPE_DIR);
				}
				else if(entry.attributes.isRegularFile()){
					row.add(Document.COLUMN_MIME_TYPE,getMime(entry.filename));
		String filename = parentDocumentId.substring(parentDocumentId.indexOf("/") + 1);
		try {
			Vector<SFTPv3DirectoryEntry> res = sftp.ls(filename);
			for (SFTPv3DirectoryEntry entry : res) {
				Log.v("SFTP",
					"qcf " + parentDocumentId + " " + entry.filename + " "
						+ entry.attributes.size + " "
						+ entry.attributes.mtime);
				if (entry.filename.equals(".") || entry.filename.equals(".."))
					continue;
				MatrixCursor.RowBuilder row = result.newRow();
				row.add(Document.COLUMN_DOCUMENT_ID,
					parentDocumentId + '/' + entry.filename);
				row.add(Document.COLUMN_DISPLAY_NAME, entry.filename);
				if (entry.attributes.isDirectory()) {
					row.add(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR);
				} else if (entry.attributes.isRegularFile()) {
					row.add(Document.COLUMN_MIME_TYPE, getMime(entry.filename));
				}
				row.add(Document.COLUMN_SIZE,entry.attributes.size);
				row.add(Document.COLUMN_LAST_MODIFIED,entry.attributes.mtime*1000);
				row.add(Document.COLUMN_SIZE, entry.attributes.size);
				row.add(Document.COLUMN_LAST_MODIFIED,
					entry.attributes.mtime * 1000);
			}
		}
		catch(Exception e){
			Log.e("SFTP","qcf "+parentDocumentId+" "+e.toString());
			Message msg=lthread.handler.obtainMessage();
			msg.obj=e.toString();
		} catch (Exception e) {
			Log.e("SFTP", "qcf " + parentDocumentId + " " + e.toString());
			Message msg = lthread.handler.obtainMessage();
			msg.obj = e.toString();
			lthread.handler.sendMessage(msg);
		}
		sftp.close();


@@ 189,28 188,30 @@ public class SFTPDocumentsProvider extends DocumentsProvider {
	}

	public Cursor queryDocument(String documentId, String[] projection) {
		MatrixCursor result=new MatrixCursor(projection!=null?projection:DEFAULT_DOC_PROJECTION);
		Log.v("SFTP","qf "+documentId+" on "+host+":"+port);
		MatrixCursor result =
			new MatrixCursor(projection != null ? projection : DEFAULT_DOC_PROJECTION);
		Log.v("SFTP", "qf " + documentId + " on " + host + ":" + port);
		editPolicyIfMainThread();
		SFTPv3Client sftp;
		if((sftp=retriveConnection())==null){
			//TODO notify error
		if ((sftp = retriveConnection()) == null) {
			// TODO notify error
			return result;
		}
		String filename=documentId.substring(documentId.indexOf("/")+1);
		try{
			SFTPv3FileAttributes res=sftp.stat(filename);
			MatrixCursor.RowBuilder row=result.newRow();
			row.add(Document.COLUMN_DOCUMENT_ID,documentId);
			row.add(Document.COLUMN_DISPLAY_NAME,filename.substring(filename.lastIndexOf("/")+1));
			row.add(Document.COLUMN_MIME_TYPE,res.isDirectory()?Document.MIME_TYPE_DIR:getMime(filename));
			row.add(Document.COLUMN_SIZE,res.size);
			row.add(Document.COLUMN_LAST_MODIFIED,res.mtime*1000);
		}
		catch(Exception e){
			Log.e("SFTP","qf "+documentId+" "+e.toString());
			Message msg=lthread.handler.obtainMessage();
			msg.obj=e.toString();
		String filename = documentId.substring(documentId.indexOf("/") + 1);
		try {
			SFTPv3FileAttributes res = sftp.stat(filename);
			MatrixCursor.RowBuilder row = result.newRow();
			row.add(Document.COLUMN_DOCUMENT_ID, documentId);
			row.add(Document.COLUMN_DISPLAY_NAME,
				filename.substring(filename.lastIndexOf("/") + 1));
			row.add(Document.COLUMN_MIME_TYPE,
				res.isDirectory() ? Document.MIME_TYPE_DIR : getMime(filename));
			row.add(Document.COLUMN_SIZE, res.size);
			row.add(Document.COLUMN_LAST_MODIFIED, res.mtime * 1000);
		} catch (Exception e) {
			Log.e("SFTP", "qf " + documentId + " " + e.toString());
			Message msg = lthread.handler.obtainMessage();
			msg.obj = e.toString();
			lthread.handler.sendMessage(msg);
		}
		sftp.close();


@@ 221,22 222,22 @@ public class SFTPDocumentsProvider extends DocumentsProvider {
		try {
			connection.ping();
			connection.close();
		}
		catch(Exception e){
		}
		MatrixCursor result=new MatrixCursor(projection!=null?projection:DEFAULT_ROOT_PROJECTION);
		SharedPreferences settings=PreferenceManager
			.getDefaultSharedPreferences(getContext());
		host=settings.getString("host","");
		port=settings.getString("port","22");
		String mountpoint=settings.getString("mountpoint",".");
		if(mountpoint.equals(""))mountpoint=".";
		MatrixCursor.RowBuilder row=result.newRow();
		row.add(Root.COLUMN_ROOT_ID,host+":"+port);
		row.add(Root.COLUMN_DOCUMENT_ID,host+":"+port+"/"+mountpoint);
		row.add(Root.COLUMN_FLAGS,0);
		row.add(Root.COLUMN_TITLE,"SFTP "+host+":"+port);
		row.add(Root.COLUMN_ICON,R.mipmap.sym_def_app_icon);
		} catch (Exception e) {
		}
		MatrixCursor result =
			new MatrixCursor(projection != null ? projection : DEFAULT_ROOT_PROJECTION);
		SharedPreferences settings =
			PreferenceManager.getDefaultSharedPreferences(getContext());
		host = settings.getString("host", "");
		port = settings.getString("port", "22");
		String mountpoint = settings.getString("mountpoint", ".");
		if (mountpoint.equals("")) mountpoint = ".";
		MatrixCursor.RowBuilder row = result.newRow();
		row.add(Root.COLUMN_ROOT_ID, host + ":" + port);
		row.add(Root.COLUMN_DOCUMENT_ID, host + ":" + port + "/" + mountpoint);
		row.add(Root.COLUMN_FLAGS, 0);
		row.add(Root.COLUMN_TITLE, "SFTP " + host + ":" + port);
		row.add(Root.COLUMN_ICON, R.mipmap.sym_def_app_icon);
		return result;
	}
}

M src/main/java/org/safsftp/SFTPProxyFileDescriptorCallback.java => src/main/java/org/safsftp/SFTPProxyFileDescriptorCallback.java +3 -4
@@ 14,7 14,6 @@ public class SFTPProxyFileDescriptorCallback extends ProxyFileDescriptorCallback
	private SFTPv3Client sftp;
	private SFTPv3FileHandle file;


	public SFTPProxyFileDescriptorCallback(SFTPv3Client sftp, SFTPv3FileHandle file) {
		this.sftp = sftp;
		this.file = file;


@@ 30,8 29,7 @@ public class SFTPProxyFileDescriptorCallback extends ProxyFileDescriptorCallback
	}

	@Override
	public int onRead(long offset, int size, byte[] data)
		throws ErrnoException {
	public int onRead(long offset, int size, byte[] data) throws ErrnoException {
		try {
			return sftp.read(file, offset, data, 0, size);
		} catch (IOException e) {


@@ 43,6 41,7 @@ public class SFTPProxyFileDescriptorCallback extends ProxyFileDescriptorCallback
	public void onRelease() {
		try {
			sftp.closeFile(file);
		} catch (IOException e) {} //TODO
		} catch (IOException e) {
		} // TODO
	}
}

M src/main/java/org/safsftp/ToastThread.java => src/main/java/org/safsftp/ToastThread.java +5 -5
@@ 10,18 10,18 @@ public class ToastThread extends Thread {
	public Handler handler;
	private Context context;

	public ToastThread(Context context){
		this.context=context;
	public ToastThread(Context context) {
		this.context = context;
	}

	public void run() {
		Looper.prepare();
		handler=new Handler() {
		handler = new Handler() {
			public void handleMessage(Message msg) {
				Toast.makeText(context,(String)msg.obj,Toast.LENGTH_SHORT).show();
				Toast.makeText(context, (String) msg.obj, Toast.LENGTH_SHORT)
					.show();
			}
		};
		Looper.loop();
	}
}