mirror of
http://galexander.org/git/simplesshd.git
synced 2024-11-30 11:18:12 +00:00
first draft of new authorized_keys creation activity and support threads
This commit is contained in:
parent
65d628499b
commit
84f9f31c14
@ -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">
|
||||||
|
@ -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"
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
59
src/org/galexander/sshd/AuthKeysFetch.java
Normal file
59
src/org/galexander/sshd/AuthKeysFetch.java
Normal 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) { }
|
||||||
|
}
|
||||||
|
}
|
54
src/org/galexander/sshd/AuthKeysLoad.java
Normal file
54
src/org/galexander/sshd/AuthKeysLoad.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
src/org/galexander/sshd/AuthKeysSave.java
Normal file
36
src/org/galexander/sshd/AuthKeysSave.java
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user