1
0
mirror of http://galexander.org/git/simplesshd.git synced 2024-11-30 19:28:10 +00:00

first draft of new authorized_keys creation activity and support threads

This commit is contained in:
Greg Alexander 2016-06-19 15:44:44 -04:00
parent 65d628499b
commit 84f9f31c14
7 changed files with 265 additions and 20 deletions

View File

@ -16,6 +16,8 @@
</activity> </activity>
<activity android:name="Settings" android:label="Settings" /> <activity android:name="Settings" android:label="Settings" />
<activity android:name="AuthKeys" android:label="Authorized Keys" /> <activity android:name="AuthKeys" android:label="Authorized Keys" />
<service android:name="AuthKeysSave" android:label="AuthKeysSave" />
<service android:name="AuthKeysFetch" android:label="AuthKeysFetch" />
<service android:name="SimpleSSHDService" <service android:name="SimpleSSHDService"
android:label="SimpleSSHDService" /> android:label="SimpleSSHDService" />
<receiver android:name="BootReceiver"> <receiver android:name="BootReceiver">

View File

@ -15,7 +15,7 @@
android:background="#00000000" /> android:background="#00000000" />
<LinearLayout <LinearLayout
android:orientation="horizontal" android:orientation="horizontal"
android_layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<Button android:id="@+id/fetch_auth" <Button android:id="@+id/fetch_auth"
android:layout_width="1dp" android:layout_width="1dp"

View File

@ -1,52 +1,125 @@
package org.galexander.sshd; package org.galexander.sshd;
import android.app.Activity; import android.app.Activity;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.widget.EditText; import android.widget.EditText;
import android.view.View; import android.view.View;
public class AuthKeys extends Activity { public class AuthKeys extends Activity {
private static final Object lock = new Object();
private EditText authtext; private EditText authtext;
private String authtext_str; private String authtext_orig;
private long authtext_when; /* XXX - type for timestamp?? */
private boolean authtext_needs_save;
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.authkeys); setContentView(R.layout.authkeys);
authtext = (EditText)findViewById(R.id.authtext); authtext = (EditText)findViewById(R.id.authtext);
authtext_str = null; authtext_orig = null;
authtext_needs_save = false;
authtext_when = 0;
/* XXX - disable R.id.save_auth */
} }
/* XXX - on changes to authtext, enable R.id.save_auth, and set authtext_needs_save */
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
/* XXX - start a thread that reads /sdcard/ssh/authorized_keys, updates authtext, iff authorized_keys is newer than authtext_when. sets authtext_when to now if it read anything. otherwise sets authtext from authtext_str */ AuthKeysLoad.go(this);
} }
public void onPause() { public void onPause() {
authtext_str = authtext.getText().toString(); save_authtext();
/* XXX - if unsaved changes, toast notify of them */
super.onPause(); super.onPause();
} }
public void fetch_clicked(View v) { public void fetch_clicked(View v) {
/* XXX - dialog to ask for http...when that dialog is done, AlertDialog.Builder ab = new AlertDialog.Builder(this);
* start thread that grabs the http and then appends its ab.setTitle("Fetch authorized_keys");
* contents to authtext */ final EditText url = new EditText(this);
url.setInputType(EditText.TYPE_CLASS_TEXT |
EditText.TYPE_TEXT_VARIATION_URI);
ab.setView(url);
ab.setPositiveButton("OK",
new DialogInterface.onClickListener() {
public void onClick(DialogInterface d, int which) {
start_fetch(url.getText().toString());
} });
ab.setNegativeButton("Cancel",
new DialogInterface.onClickListener() {
public void onClick(DialogInterface d, int which) {
d.cancel();
} });
ab.show();
} }
public void cancel_clicked(View v) { public void cancel_clicked(View v) {
authtext_str = null; authtext_orig = null;
authtext_when = 0; finish();
} }
public void save_clicked(View v) { public void save_clicked(View v) {
/* XXX - start thread that writes to file */ save_authtext();
finish();
}
private void save_authtext() {
String s = get_authtext();
if ((authtext_orig_str != null) && (s != null) &&
!s.equals(authtext_orig)) {
Intent i = new Intent(this, AuthKeysSave.class);
i.putExtra("s", s);
startService(i);
}
}
private String get_authtext() {
if (authtext != null) {
return authtext.getText().toString();
}
return null;
}
/* called from AuthKeysLoad, which puts it on the UI thread */
public void set_authtext(String s) {
if (authtext != null) {
authtext.setText(s);
authtext_orig = s;
}
}
/* called from AuthKeysFetch, from its own thread */
public void append_authtext(String s) {
if (authtext != null) {
String t = get_authtext();
if (t == null) {
t = "";
}
if (!t.endsWith("\n")) {
t += "\n";
}
t += s;
authtext.setText(t);
}
}
private void start_fetch(String url) {
Intent i = new Intent(this, AuthKeysFetch.class);
i.putExtra("url", url.getText().toString());
i.putExtra("m", Messenger m = new Messenger(new Handler() {
public void handleMessage(Message msg) {
Object o = msg.obj;
if (o == null) {
return;
}
String s = (String)o;
int n = msg.arg1;
if (n == 0) {
/* s is data read from the url */
append_authtext(s);
} else {
/* s must be an error message */
Toast.makeText(this, s,
Toast.LENGTH_LONG).show();
}
} } ));
startService(i);
} }
} }

View File

@ -0,0 +1,59 @@
package org.galexander.sshd;
import android.app.IntentService;
import android.content.Intent;
import android.os.Message;
import android.os.Messenger;
import java.net.URL;
import java.net.HttpURLConnection;
public class AuthKeysSave extends IntentService {
public AuthKeysSave() {
super("SimpleSSHDAuthKeysSave");
}
protected void onHandleIntent(Intent i) {
Messenger m = (Messenger)i.getExtra("m");
Message msg = m.obtain();
String url = i.getStringExtra("url", null);
String result = "";
byte[] b = new byte[1024];
try {
if (url == null) {
throw new Exception("no url");
}
URL u = new URL(url);
HttpURLConnection conn = (HttpURLConnection)
url.openConnection();
try {
InputStream in = conn.getInputStream();
try {
while (result.length() < 65536) {
int r = in.read(b);
if (r <= 0) {
break;
}
result += new String(b, 0, r);
}
} finally {
in.close();
}
} finally {
conn.disconnect();
}
if (result.equals("")) {
throw new Exception("empty file");
}
msg.arg1 = 0;
msg.obj = result;
} catch (Exception e) {
msg.arg1 = 1;
msg.obj = "HTTP fetch: " + e.getMessage();
}
try {
m.send(msg);
} catch (Exception e) { }
}
}

View File

@ -0,0 +1,54 @@
package org.galexander.sshd;
import android.app.Activity;
import android.os.AsyncTask;
public class AuthKeysLoad extends AsyncTask<Void,Void,Void> {
private AuthKeys act = null;
private String result = null;
private String error = null;
public static void go(AuthKeys act_) {
(new AuthKeysLoad(act_)).execute();
}
AuthKeysLoad(AuthKeys act_) {
act = act_;
super();
}
protected Void doInBackground(Void... v) {
try {
File f = new File(Prefs.get_path(), "authorized_keys");
FileInputStream fis = new FileInputStream(f);
byte b[] = new byte[1024];
result = "";
try {
while (true) {
int r = fis.read(b);
if (r <= 0) {
break;
}
result += new String(b, 0, r);
}
} finally {
fis.close();
}
} catch (Exception e) {
error = e.getMessage();
}
return null;
}
protected void onPostExecute(Void v) {
if (result != null) {
act.set_authtext(result);
} else if (error != null) {
Toast.makeText(act,
"failed to load authorized_keys: " + error,
Toast.LENGTH_LONG).show();
}
}
}

View File

@ -0,0 +1,36 @@
package org.galexander.sshd;
import android.app.IntentService;
import android.content.Intent;
import java.io.File;
import java.io.FileOutputStream;
public class AuthKeysSave extends IntentService {
public AuthKeysSave() {
super("SimpleSSHDAuthKeysSave");
}
protected void onHandleIntent(Intent i) {
String s = i.getStringExtra("s", null);
if (s == null) {
return;
}
try {
File p = new File(Prefs.get_path());
if (!p.exists()) {
p.mkdirs();
}
File f = new File(p, "authorized_keys");
FileOutputStream fos = new FileOutputStream(f);
int ofs = 0;
try {
fos.write(s.getBytes());
} finally {
fos.close();
}
} catch (Exception e) {
SimpleSSHD.toast(
"authorized_keys save failed: "+e.getMessage());
}
}
}

View File

@ -31,6 +31,7 @@ public class SimpleSSHD extends Activity
private TextView ip_view; private TextView ip_view;
public static SimpleSSHD curr = null; public static SimpleSSHD curr = null;
private UpdaterThread updater = null; private UpdaterThread updater = null;
private static String pending_toast = null;
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -45,6 +46,11 @@ public class SimpleSSHD extends Activity
super.onResume(); super.onResume();
synchronized (lock) { synchronized (lock) {
curr = this; curr = this;
if (pending_toast != null) {
Toast.makeText(this, pending_toast,
Toast.LENGTH_LONG).show();
pending_toast = null;
}
} }
update_startstop_prime(); update_startstop_prime();
updater = new UpdaterThread(); updater = new UpdaterThread();
@ -218,4 +224,19 @@ public class SimpleSSHD extends Activity
return "UNKNOWN"; return "UNKNOWN";
} }
} }
/* called from AuthKeysSave (in its own worker thread) if it fails */
public static void toast(String s) {
synchronized (lock) {
if (curr != null) {
curr.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(this, s,
Toast.LENGTH_LONG).show();
} });
} else {
pending_toast = s;
}
}
}
} }