aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKenny Root <kenny@the-b.org>2009-01-23 13:38:50 +0000
committerKenny Root <kenny@the-b.org>2009-01-23 13:38:50 +0000
commitaed1876f36b34ee62e1537d42fcb339c6baa05b0 (patch)
tree7dba778a44d6d26201b24552854089e640235e33 /src
parentf4ade61e9ff1e80918509544e2bdf3a26bca5edc (diff)
downloadconnectbot-aed1876f36b34ee62e1537d42fcb339c6baa05b0.tar.gz
connectbot-aed1876f36b34ee62e1537d42fcb339c6baa05b0.tar.bz2
connectbot-aed1876f36b34ee62e1537d42fcb339c6baa05b0.zip
Indentation cleanup, pass 1
* Change 4-spaces to tabs (I blame Eclipse's editor) * Remove white spaces from end of lines
Diffstat (limited to 'src')
-rw-r--r--src/org/connectbot/ConsoleActivity.java268
-rw-r--r--src/org/connectbot/GeneratePubkeyActivity.java108
-rw-r--r--src/org/connectbot/HelpActivity.java16
-rw-r--r--src/org/connectbot/HelpTopicActivity.java16
-rw-r--r--src/org/connectbot/HostEditorActivity.java94
-rw-r--r--src/org/connectbot/HostListActivity.java160
-rw-r--r--src/org/connectbot/PortForwardListActivity.java158
-rw-r--r--src/org/connectbot/PubkeyListActivity.java176
-rw-r--r--src/org/connectbot/SettingsActivity.java6
-rw-r--r--src/org/connectbot/TerminalView.java44
-rw-r--r--src/org/connectbot/WizardActivity.java30
-rw-r--r--src/org/connectbot/bean/AbstractBean.java12
-rw-r--r--src/org/connectbot/bean/HostBean.java42
-rw-r--r--src/org/connectbot/bean/PortForwardBean.java52
-rw-r--r--src/org/connectbot/bean/PubkeyBean.java24
-rw-r--r--src/org/connectbot/bean/SelectionArea.java76
-rw-r--r--src/org/connectbot/service/BridgeDisconnectedListener.java6
-rw-r--r--src/org/connectbot/service/PromptHelper.java40
-rw-r--r--src/org/connectbot/service/TerminalBridge.java438
-rw-r--r--src/org/connectbot/service/TerminalManager.java108
-rw-r--r--src/org/connectbot/util/Encryptor.java334
-rw-r--r--src/org/connectbot/util/EntropyDialog.java12
-rw-r--r--src/org/connectbot/util/EntropyView.java170
-rw-r--r--src/org/connectbot/util/HelpTopicView.java14
-rw-r--r--src/org/connectbot/util/HostDatabase.java146
-rw-r--r--src/org/connectbot/util/OnEntropyGatheredListener.java6
-rw-r--r--src/org/connectbot/util/PubkeyDatabase.java124
-rw-r--r--src/org/connectbot/util/PubkeyUtils.java110
-rw-r--r--src/org/connectbot/util/UpdateHelper.java66
-rw-r--r--src/org/connectbot/util/XmlBuilder.java22
30 files changed, 1439 insertions, 1439 deletions
diff --git a/src/org/connectbot/ConsoleActivity.java b/src/org/connectbot/ConsoleActivity.java
index fd9dbcc..ab06d83 100644
--- a/src/org/connectbot/ConsoleActivity.java
+++ b/src/org/connectbot/ConsoleActivity.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -71,19 +71,19 @@ public class ConsoleActivity extends Activity {
public final static String TAG = ConsoleActivity.class.toString();
protected static final int REQUEST_EDIT = 1;
-
+
protected ViewFlipper flip = null;
protected TerminalManager bound = null;
protected LayoutInflater inflater = null;
-
- private SharedPreferences prefs = null;
-
+
+ private SharedPreferences prefs = null;
+
private PowerManager.WakeLock wakelock = null;
-
+
private String PREF_KEEPALIVE = null;
-
+
protected Uri requested;
-
+
protected ClipboardManager clipboard;
private RelativeLayout stringPromptGroup;
protected EditText stringPrompt;
@@ -93,35 +93,35 @@ public class ConsoleActivity extends Activity {
private Button booleanYes, booleanNo;
private TextView empty;
-
+
private Animation slide_left_in, slide_left_out, slide_right_in, slide_right_out, fade_stay_hidden, fade_out;
-
+
private MenuItem disconnect, copy, paste, portForward, resize;
-
+
protected TerminalBridge copySource = null;
private int lastTouchRow, lastTouchCol;
-
+
private ServiceConnection connection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
bound = ((TerminalManager.TerminalBinder) service).getService();
-
+
// let manager know about our event handling services
bound.disconnectHandler = disconnectHandler;
-
+
Log.d(TAG, String.format("Connected to TerminalManager and found bridges.size=%d", bound.bridges.size()));
-
+
// clear out any existing bridges and record requested index
flip.removeAllViews();
String requestedNickname = (requested != null) ? requested.getFragment() : null;
int requestedIndex = 0;
-
+
// first check if we need to create a new session for requested
boolean found = false;
for(TerminalBridge bridge : bound.bridges) {
if(bridge.host.getNickname().equals(requestedNickname))
found = true;
}
-
+
// If we didn't find the requested connection, try opening it
if(!found) {
try {
@@ -131,35 +131,35 @@ public class ConsoleActivity extends Activity {
Log.e(TAG, "Problem while trying to create new requested bridge from URI", e);
}
}
-
+
// create views for all bridges on this service
for(TerminalBridge bridge : bound.bridges) {
-
+
// let them know about our prompt handler services
bridge.promptHelper.setHandler(promptHandler);
bridge.refreshKeymode();
-
+
// inflate each terminal view
RelativeLayout view = (RelativeLayout)inflater.inflate(R.layout.item_terminal, flip, false);
-
+
// set the terminal overlay text
TextView overlay = (TextView)view.findViewById(R.id.terminal_overlay);
overlay.setText(bridge.host.getNickname());
-
+
// and add our terminal view control, using index to place behind overlay
TerminalView terminal = new TerminalView(ConsoleActivity.this, bridge);
terminal.setId(R.id.console_flip);
view.addView(terminal, 0);
-
+
// finally attach to the flipper
flip.addView(view);
-
+
// check to see if this bridge was requested
if(bridge.host.getNickname().equals(requestedNickname))
requestedIndex = flip.getChildCount() - 1;
-
+
}
-
+
try {
// show the requested bridge if found, also fade out overlay
flip.setDisplayedChild(requestedIndex);
@@ -167,21 +167,21 @@ public class ConsoleActivity extends Activity {
} catch (NullPointerException npe) {
Log.d(TAG, "View went away when we were about to display it", npe);
}
-
+
updatePromptVisible();
updateEmptyVisible();
-
+
}
-
+
public void onServiceDisconnected(ComponentName className) {
// tell each bridge to forget about our prompt handler
for(TerminalBridge bridge : bound.bridges)
bridge.promptHelper.setHandler(null);
-
+
flip.removeAllViews();
updateEmptyVisible();
bound = null;
-
+
}
};
@@ -201,7 +201,7 @@ public class ConsoleActivity extends Activity {
// someone below us requested to display a password dialog
// they are sending nickname and requested
TerminalBridge bridge = (TerminalBridge)msg.obj;
-
+
if (bridge.isAwaitingClose())
closeBridge(bridge);
}
@@ -213,18 +213,18 @@ public class ConsoleActivity extends Activity {
private void closeBridge(TerminalBridge bridge) {
for(int i = 0; i < flip.getChildCount(); i++) {
View child = flip.getChildAt(i).findViewById(R.id.console_flip);
-
+
if (!(child instanceof TerminalView)) continue;
-
+
TerminalView terminal = (TerminalView) child;
-
+
if (terminal.bridge.equals(bridge)) {
// we've found the terminal to remove
// shift something into its place if currently visible
if(flip.getDisplayedChild() == i)
shiftLeft();
flip.removeViewAt(i);
-
+
/* TODO Remove this workaround when ViewFlipper is fixed to listen
* to view removals. Android Issue 1784
*/
@@ -232,18 +232,18 @@ public class ConsoleActivity extends Activity {
if (flip.getDisplayedChild() >= numChildren &&
numChildren > 0)
flip.setDisplayedChild(numChildren - 1);
-
+
updateEmptyVisible();
break;
}
}
-
+
// If we just closed the last bridge, go back to the previous activity.
if (flip.getChildCount() == 0) {
finish();
}
}
-
+
// TODO review use (apparently unused)
protected void createPortForward(TerminalView target, String nickname, String type, String source, String dest) {
String summary = getString(R.string.portforward_problem);
@@ -251,7 +251,7 @@ public class ConsoleActivity extends Activity {
long hostId = target.bridge.host.getId();
PortForwardBean pfb = new PortForwardBean(hostId, nickname, type, source, dest);
-
+
target.bridge.addPortForward(pfb);
if (target.bridge.enablePortForward(pfb)) {
summary = getString(R.string.portforward_done);
@@ -259,23 +259,23 @@ public class ConsoleActivity extends Activity {
} catch(Exception e) {
Log.e(TAG, "Problem trying to create portForward", e);
}
-
+
Toast.makeText(ConsoleActivity.this, summary, Toast.LENGTH_LONG).show();
}
-
+
protected View findCurrentView(int id) {
View view = flip.getCurrentView();
if(view == null) return null;
return view.findViewById(id);
}
-
+
// TODO review use (apparently unused)
protected HostBean getCurrentHost() {
View view = findCurrentView(R.id.console_flip);
if(!(view instanceof TerminalView)) return null;
return ((TerminalView)view).bridge.host;
}
-
+
protected PromptHelper getCurrentPromptHelper() {
View view = findCurrentView(R.id.console_flip);
if(!(view instanceof TerminalView)) return null;
@@ -288,20 +288,20 @@ public class ConsoleActivity extends Activity {
}
@Override
- public void onCreate(Bundle icicle) {
+ public void onCreate(Bundle icicle) {
super.onCreate(icicle);
-
+
this.setContentView(R.layout.act_console);
-
+
clipboard = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE);
prefs = PreferenceManager.getDefaultSharedPreferences(this);
-
+
// hide status bar if requested by user
if (prefs.getBoolean(getString(R.string.pref_fullscreen), false)) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
-
+
// request a forced orientation if requested by user
String rotate = prefs.getString(getString(R.string.pref_rotation), getString(R.string.list_rotation_land));
if(getString(R.string.list_rotation_land).equals(rotate)) {
@@ -309,33 +309,33 @@ public class ConsoleActivity extends Activity {
} else if (getString(R.string.list_rotation_port).equals(rotate)) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
-
+
// TODO find proper way to disable volume key beep if it exists.
setVolumeControlStream(AudioManager.STREAM_MUSIC);
-
- PowerManager manager = (PowerManager)getSystemService(Context.POWER_SERVICE);
+
+ PowerManager manager = (PowerManager)getSystemService(Context.POWER_SERVICE);
wakelock = manager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, TAG);
-
+
PREF_KEEPALIVE = getResources().getString(R.string.pref_keepalive);
// handle requested console from incoming intent
requested = getIntent().getData();
inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
+
flip = (ViewFlipper)findViewById(R.id.console_flip);
empty = (TextView)findViewById(android.R.id.empty);
-
+
stringPromptGroup = (RelativeLayout) findViewById(R.id.console_password_group);
stringPrompt = (EditText)findViewById(R.id.console_password);
stringPrompt.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
if(event.getAction() == KeyEvent.ACTION_UP) return false;
if(keyCode != KeyEvent.KEYCODE_ENTER) return false;
-
+
// pass collected password down to current terminal
String value = stringPrompt.getText().toString();
-
+
PromptHelper helper = getCurrentPromptHelper();
if(helper == null) return false;
helper.setResponse(value);
@@ -347,10 +347,10 @@ public class ConsoleActivity extends Activity {
return true;
}
});
-
+
booleanPromptGroup = (RelativeLayout) findViewById(R.id.console_boolean_group);
booleanPrompt = (TextView)findViewById(R.id.console_prompt);
-
+
booleanYes = (Button)findViewById(R.id.console_prompt_yes);
booleanYes.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
@@ -360,7 +360,7 @@ public class ConsoleActivity extends Activity {
hideAllPrompts();
}
});
-
+
booleanNo = (Button)findViewById(R.id.console_prompt_no);
booleanNo.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
@@ -370,23 +370,23 @@ public class ConsoleActivity extends Activity {
hideAllPrompts();
}
});
-
+
// preload animations for terminal switching
slide_left_in = AnimationUtils.loadAnimation(this, R.anim.slide_left_in);
slide_left_out = AnimationUtils.loadAnimation(this, R.anim.slide_left_out);
slide_right_in = AnimationUtils.loadAnimation(this, R.anim.slide_right_in);
slide_right_out = AnimationUtils.loadAnimation(this, R.anim.slide_right_out);
-
+
fade_out = AnimationUtils.loadAnimation(this, R.anim.fade_out);
fade_stay_hidden = AnimationUtils.loadAnimation(this, R.anim.fade_stay_hidden);
-
+
// detect fling gestures to switch between terminals
- final GestureDetector detect = new GestureDetector(new GestureDetector.SimpleOnGestureListener() {
+ final GestureDetector detect = new GestureDetector(new GestureDetector.SimpleOnGestureListener() {
private float totalY = 0;
-
+
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
-
+
float distx = e2.getRawX() - e1.getRawX();
float disty = e2.getRawY() - e1.getRawY();
int goalwidth = flip.getWidth() / 2;
@@ -398,25 +398,25 @@ public class ConsoleActivity extends Activity {
shiftRight();
return true;
}
-
+
if(distx < -goalwidth) {
shiftLeft();
return true;
}
-
+
}
-
+
return false;
}
-
-
+
+
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
-
+
// if copying, then ignore
if (copySource != null && copySource.isSelectingForCopy())
return false;
-
+
if (e1 == null || e2 == null)
return false;
@@ -424,10 +424,10 @@ public class ConsoleActivity extends Activity {
if(e2.getAction() == MotionEvent.ACTION_UP) {
totalY = 0;
}
-
+
// activate consider if within x tolerance
if(Math.abs(e1.getX() - e2.getX()) < ViewConfiguration.getTouchSlop() * 4) {
-
+
View flip = findCurrentView(R.id.console_flip);
if(flip == null) return false;
TerminalView terminal = (TerminalView)flip;
@@ -436,7 +436,7 @@ public class ConsoleActivity extends Activity {
// accumulate distance that doesn't trigger immediate scroll
totalY += distanceY;
int moved = (int)(totalY / terminal.bridge.charHeight);
-
+
// consume as scrollback only if towards right half of screen
if (e2.getX() > flip.getWidth() / 2.0) {
if(moved != 0) {
@@ -458,29 +458,29 @@ public class ConsoleActivity extends Activity {
totalY = 0;
return true;
}
-
+
}
-
+
}
-
+
return false;
}
});
-
+
flip.setLongClickable(true);
flip.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
-
+
// when copying, highlight the area
if (copySource != null && copySource.isSelectingForCopy()) {
int row = (int)Math.floor(event.getY() / copySource.charHeight);
int col = (int)Math.floor(event.getX() / copySource.charWidth);
-
+
SelectionArea area = copySource.getSelectionArea();
-
+
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
// recording starting area
@@ -498,10 +498,10 @@ public class ConsoleActivity extends Activity {
*/
if (row == lastTouchRow && col == lastTouchCol)
return true;
-
+
// if the user moves, start the selection for other corner
area.finishSelectingOrigin();
-
+
// update selected area
area.setBottom(row);
area.setRight(col);
@@ -517,14 +517,14 @@ public class ConsoleActivity extends Activity {
area.getTop() == area.getBottom()) {
return true;
}
-
+
// copy selected area to clipboard
String copiedText = area.copyFrom(copySource.buffer);
-
+
clipboard.setText(copiedText);
Toast.makeText(ConsoleActivity.this, getString(R.string.console_copy_done, copiedText.length()), Toast.LENGTH_LONG).show();
// fall through to clear state
-
+
case MotionEvent.ACTION_CANCEL:
// make sure we clear any highlighted area
area.reset();
@@ -532,36 +532,36 @@ public class ConsoleActivity extends Activity {
copySource.redraw();
return true;
}
-
-
+
+
}
-
+
// pass any touch events back to detector
return detect.onTouchEvent(event);
}
-
+
});
-
+
}
-
+
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
-
+
final View view = findCurrentView(R.id.console_flip);
final boolean activeTerminal = (view instanceof TerminalView);
boolean authenticated = false;
boolean sessionOpen = false;
boolean disconnected = false;
-
+
if (activeTerminal) {
authenticated = ((TerminalView) view).bridge.isAuthenticated();
sessionOpen = ((TerminalView) view).bridge.isSessionOpen();
disconnected = ((TerminalView) view).bridge.isDisconnected();
}
-
-
+
+
disconnect = menu.add(R.string.console_menu_disconnect);
if (!sessionOpen && disconnected)
disconnect.setTitle(R.string.console_menu_close);
@@ -575,7 +575,7 @@ public class ConsoleActivity extends Activity {
return true;
}
});
-
+
copy = menu.add(R.string.console_menu_copy);
copy.setIcon(android.R.drawable.ic_menu_set_as);
copy.setEnabled(activeTerminal);
@@ -583,22 +583,22 @@ public class ConsoleActivity extends Activity {
public boolean onMenuItemClick(MenuItem item) {
// mark as copying and reset any previous bounds
copySource = ((TerminalView)view).bridge;
-
+
SelectionArea area = copySource.getSelectionArea();
area.reset();
area.setBounds(copySource.buffer.getColumns(), copySource.buffer.getRows());
-
+
copySource.setSelectingForCopy(true);
-
+
// Make sure we show the initial selection
copySource.redraw();
-
+
Toast.makeText(ConsoleActivity.this, getString(R.string.console_copy_start), Toast.LENGTH_LONG).show();
return true;
}
});
-
+
paste = menu.add(R.string.console_menu_paste);
paste.setIcon(android.R.drawable.ic_menu_edit);
paste.setEnabled(clipboard.hasText() && activeTerminal && authenticated);
@@ -606,7 +606,7 @@ public class ConsoleActivity extends Activity {
public boolean onMenuItemClick(MenuItem item) {
// force insert of clipboard text into current console
TerminalView terminal = (TerminalView)view;
-
+
// pull string from clipboard and generate all events to force down
String clip = clipboard.getText().toString();
terminal.bridge.injectString(clip);
@@ -614,8 +614,8 @@ public class ConsoleActivity extends Activity {
return true;
}
});
-
-
+
+
portForward = menu.add(R.string.console_menu_portforwards);
portForward.setIcon(android.R.drawable.ic_menu_manage);
portForward.setEnabled(authenticated);
@@ -627,14 +627,14 @@ public class ConsoleActivity extends Activity {
return true;
}
});
-
+
resize = menu.add(R.string.console_menu_resize);
resize.setIcon(android.R.drawable.ic_menu_crop);
resize.setEnabled(activeTerminal && sessionOpen);
resize.setOnMenuItemClickListener(new OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
final TerminalView terminal = (TerminalView)view;
-
+
final View resizeView = inflater.inflate(R.layout.dia_resize, null, false);
new AlertDialog.Builder(ConsoleActivity.this)
.setView(resizeView)
@@ -642,22 +642,22 @@ public class ConsoleActivity extends Activity {
public void onClick(DialogInterface dialog, int which) {
int width = Integer.parseInt(((EditText)resizeView.findViewById(R.id.width)).getText().toString());
int height = Integer.parseInt(((EditText)resizeView.findViewById(R.id.height)).getText().toString());
-
+
terminal.forceSize(width, height);
}
}).setNegativeButton(android.R.string.cancel, null).create().show();
-
+
return true;
}
});
return true;
}
-
+
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
-
+
final View view = findCurrentView(R.id.console_flip);
boolean activeTerminal = (view instanceof TerminalView);
boolean authenticated = false;
@@ -668,7 +668,7 @@ public class ConsoleActivity extends Activity {
sessionOpen = ((TerminalView)view).bridge.isSessionOpen();
disconnected = ((TerminalView)view).bridge.isDisconnected();
}
-
+
disconnect.setEnabled(activeTerminal);
if (sessionOpen || !disconnected)
disconnect.setTitle(R.string.console_menu_disconnect);
@@ -681,22 +681,22 @@ public class ConsoleActivity extends Activity {
return true;
}
-
+
@Override
- public void onStart() {
+ public void onStart() {
super.onStart();
// connect with manager service to find all bridges
// when connected it will insert all views
- bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE);
+ bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE);
- // make sure we dont let the screen fall asleep
+ // make sure we dont let the screen fall asleep
// this also keeps the wifi chipset from disconnecting us
if(wakelock != null && prefs.getBoolean(PREF_KEEPALIVE, true))
wakelock.acquire();
}
-
+
@Override
public void onStop() {
super.onStop();
@@ -705,13 +705,13 @@ public class ConsoleActivity extends Activity {
// allow the screen to dim and fall asleep
if(wakelock != null && wakelock.isHeld())
wakelock.release();
-
+
}
-
+
protected void shiftLeft() {
View overlay;
boolean shouldAnimate = flip.getChildCount() > 1;
-
+
// Only show animation if there is something else to go to.
if (shouldAnimate) {
// keep current overlay from popping up again
@@ -723,19 +723,19 @@ public class ConsoleActivity extends Activity {
flip.setOutAnimation(slide_left_out);
flip.showNext();
}
-
+
ConsoleActivity.this.updateDefault();
-
+
if (shouldAnimate) {
// show overlay on new slide and start fade
overlay = findCurrentView(R.id.terminal_overlay);
if (overlay != null)
overlay.startAnimation(fade_out);
}
-
+
updatePromptVisible();
}
-
+
protected void shiftRight() {
View overlay;
boolean shouldAnimate = flip.getChildCount() > 1;
@@ -751,7 +751,7 @@ public class ConsoleActivity extends Activity {
flip.setOutAnimation(slide_right_out);
flip.showPrevious();
}
-
+
ConsoleActivity.this.updateDefault();
if (shouldAnimate) {
@@ -778,13 +778,13 @@ public class ConsoleActivity extends Activity {
if(bound == null) return;
bound.defaultBridge = terminal.bridge;
}
-
+
protected void updateEmptyVisible() {
// update visibility of empty status message
empty.setVisibility((flip.getChildCount() == 0) ? View.VISIBLE : View.GONE);
}
- /**
+ /**
* Show any prompts requested by the currently visible {@link TerminalView}.
*/
protected void updatePromptVisible() {
@@ -798,19 +798,19 @@ public class ConsoleActivity extends Activity {
// we dont have an active view, so hide any prompts
return;
}
-
+
PromptHelper prompt = ((TerminalView)view).bridge.promptHelper;
if(String.class.equals(prompt.promptRequested)) {
stringPromptGroup.setVisibility(View.VISIBLE);
stringPrompt.setText("");
stringPrompt.setHint(prompt.promptHint);
stringPrompt.requestFocus();
-
+
} else if(Boolean.class.equals(prompt.promptRequested)) {
booleanPromptGroup.setVisibility(View.VISIBLE);
booleanPrompt.setText(prompt.promptHint);
booleanYes.requestFocus();
-
+
} else {
hideAllPrompts();
view.requestFocus();
diff --git a/src/org/connectbot/GeneratePubkeyActivity.java b/src/org/connectbot/GeneratePubkeyActivity.java
index 5d5a4de..9408cb0 100644
--- a/src/org/connectbot/GeneratePubkeyActivity.java
+++ b/src/org/connectbot/GeneratePubkeyActivity.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -57,7 +57,7 @@ public class GeneratePubkeyActivity extends Activity implements OnEntropyGathere
public final static String TAG = GeneratePubkeyActivity.class.toString();
final static int DEFAULT_BITS = 1024;
-
+
private LayoutInflater inflater = null;
private EditText nickname;
@@ -68,80 +68,80 @@ public class GeneratePubkeyActivity extends Activity implements OnEntropyGathere
private Button save;
private Dialog entropyDialog;
private ProgressDialog progress;
-
+
private EditText password1, password2;
-
+
private String keyType = PubkeyDatabase.KEY_TYPE_RSA;
private int minBits = 768;
private int bits = DEFAULT_BITS;
-
+
private byte[] entropy;
-
+
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
-
+
setContentView(R.layout.act_generatepubkey);
-
+
nickname = (EditText) findViewById(R.id.nickname);
-
+
keyTypeGroup = (RadioGroup) findViewById(R.id.key_type);
-
+
bitsText = (EditText) findViewById(R.id.bits);
bitsSlider = (SeekBar) findViewById(R.id.bits_slider);
-
+
password1 = (EditText) findViewById(R.id.password1);
password2 = (EditText) findViewById(R.id.password2);
-
+
unlockAtStartup = (CheckBox) findViewById(R.id.unlock_at_startup);
-
+
save = (Button) findViewById(R.id.save);
-
+
inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
nickname.addTextChangedListener(textChecker);
password1.addTextChangedListener(textChecker);
password2.addTextChangedListener(textChecker);
-
+
keyTypeGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (checkedId == R.id.rsa) {
minBits = 768;
-
+
bitsSlider.setEnabled(true);
bitsSlider.setProgress(DEFAULT_BITS - minBits);
-
+
bitsText.setText(String.valueOf(DEFAULT_BITS));
bitsText.setEnabled(true);
-
+
keyType = PubkeyDatabase.KEY_TYPE_RSA;
} else if (checkedId == R.id.dsa) {
// DSA keys can only be 1024 bits
-
+
bitsSlider.setEnabled(false);
bitsSlider.setProgress(DEFAULT_BITS - minBits);
-
+
bitsText.setText(String.valueOf(DEFAULT_BITS));
bitsText.setEnabled(false);
-
+
keyType = PubkeyDatabase.KEY_TYPE_DSA;
- }
+ }
}
});
-
+
bitsSlider.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromTouch) {
// Stay evenly divisible by 8 because it looks nicer to have
// 2048 than 2043 bits.
-
+
int leftover = progress % 8;
-
+
if (leftover > 0)
progress += 8 - leftover;
-
+
bits = minBits + progress;
bitsText.setText(String.valueOf(bits));
}
@@ -154,7 +154,7 @@ public class GeneratePubkeyActivity extends Activity implements OnEntropyGathere
// We don't care about the stop.
}
});
-
+
bitsText.setOnFocusChangeListener(new OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
@@ -168,16 +168,16 @@ public class GeneratePubkeyActivity extends Activity implements OnEntropyGathere
bits = DEFAULT_BITS;
bitsText.setText(String.valueOf(bits));
}
-
+
bitsSlider.setProgress(bits - minBits);
}
}
});
-
+
save.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
GeneratePubkeyActivity.this.save.setEnabled(false);
-
+
GeneratePubkeyActivity.this.startEntropyGather();
}
});
@@ -186,36 +186,36 @@ public class GeneratePubkeyActivity extends Activity implements OnEntropyGathere
private void checkEntries() {
boolean allowSave = true;
-
+
if (!password1.getText().toString().equals(password2.getText().toString()))
allowSave = false;
-
- if (nickname.getText().length() == 0)
+
+ if (nickname.getText().length() == 0)
allowSave = false;
-
+
save.setEnabled(allowSave);
}
-
+
private void startEntropyGather() {
final View entropyView = inflater.inflate(R.layout.dia_gatherentropy, null, false);
((EntropyView)entropyView.findViewById(R.id.entropy)).addOnEntropyGatheredListener(GeneratePubkeyActivity.this);
entropyDialog = new EntropyDialog(GeneratePubkeyActivity.this, entropyView);
entropyDialog.show();
}
-
+
public void onEntropyGathered(byte[] entropy) {
// For some reason the entropy dialog was aborted, exit activity
if (entropy == null) {
finish();
return;
}
-
+
this.entropy = entropy.clone();
-
+
Log.d(TAG, "entropy gathered; attemping to generate key...");
startKeyGen();
}
-
+
private void startKeyGen() {
progress = new ProgressDialog(GeneratePubkeyActivity.this);
progress.setMessage(GeneratePubkeyActivity.this.getResources().getText(R.string.pubkey_generating));
@@ -225,38 +225,38 @@ public class GeneratePubkeyActivity extends Activity implements OnEntropyGathere
new Thread(mKeyGen).start();
}
-
+
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
progress.dismiss();
GeneratePubkeyActivity.this.finish();
}
};
-
+
final private Runnable mKeyGen = new Runnable() {
public void run() {
try {
boolean encrypted = false;
-
+
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
-
+
random.setSeed(entropy);
-
+
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(keyType);
-
+
keyPairGen.initialize(bits, random);
-
+
KeyPair pair = keyPairGen.generateKeyPair();
PrivateKey priv = pair.getPrivate();
PublicKey pub = pair.getPublic();
-
+
String secret = password1.getText().toString();
if (secret.length() > 0)
encrypted = true;
-
+
Log.d(TAG, "private: " + PubkeyUtils.formatKey(priv));
Log.d(TAG, "public: " + PubkeyUtils.formatKey(pub));
-
+
PubkeyBean pubkey = new PubkeyBean();
pubkey.setNickname(nickname.getText().toString());
pubkey.setType(keyType);
@@ -264,7 +264,7 @@ public class GeneratePubkeyActivity extends Activity implements OnEntropyGathere
pubkey.setPublicKey(PubkeyUtils.getEncodedPublic(pub));
pubkey.setEncrypted(encrypted);
pubkey.setStartup(unlockAtStartup.isChecked());
-
+
PubkeyDatabase pubkeydb = new PubkeyDatabase(GeneratePubkeyActivity.this);
pubkeydb.savePubkey(pubkey);
pubkeydb.close();
@@ -273,12 +273,12 @@ public class GeneratePubkeyActivity extends Activity implements OnEntropyGathere
e.printStackTrace();
}
-
+
handler.sendEmptyMessage(0);
}
};
-
+
final private TextWatcher textChecker = new TextWatcher() {
public void afterTextChanged(Editable s) {}
diff --git a/src/org/connectbot/HelpActivity.java b/src/org/connectbot/HelpActivity.java
index c04127f..24ff2b4 100644
--- a/src/org/connectbot/HelpActivity.java
+++ b/src/org/connectbot/HelpActivity.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -35,7 +35,7 @@ import android.widget.LinearLayout;
*/
public class HelpActivity extends Activity {
public final static String TAG = HelpActivity.class.toString();
-
+
public final static String HELPDIR = "help";
public final static String SUFFIX = ".html";
@@ -43,11 +43,11 @@ public class HelpActivity extends Activity {
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.act_help);
-
+
this.setTitle(String.format("%s: %s",
getResources().getText(R.string.app_name),
getResources().getText(R.string.title_help)));
-
+
AssetManager am = this.getAssets();
LinearLayout content = (LinearLayout)this.findViewById(R.id.topics);
@@ -57,7 +57,7 @@ public class HelpActivity extends Activity {
Button button = new Button(this);
final String topic = name.substring(0, name.length() - SUFFIX.length());
button.setText(topic);
-
+
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(HelpActivity.this, HelpTopicActivity.class);
@@ -65,7 +65,7 @@ public class HelpActivity extends Activity {
HelpActivity.this.startActivity(intent);
}
});
-
+
content.addView(button);
}
}
diff --git a/src/org/connectbot/HelpTopicActivity.java b/src/org/connectbot/HelpTopicActivity.java
index 35e23f5..6b54732 100644
--- a/src/org/connectbot/HelpTopicActivity.java
+++ b/src/org/connectbot/HelpTopicActivity.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -34,16 +34,16 @@ public class HelpTopicActivity extends Activity {
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.act_help_topic);
-
+
String topic = getIntent().getStringExtra(Intent.EXTRA_TITLE);
-
+
this.setTitle(String.format("%s: %s - %s",
getResources().getText(R.string.app_name),
getResources().getText(R.string.title_help),
topic));
-
+
HelpTopicView helpTopic = (HelpTopicView) findViewById(R.id.topic_text);
-
- helpTopic.setTopic(topic);
+
+ helpTopic.setTopic(topic);
}
}
diff --git a/src/org/connectbot/HostEditorActivity.java b/src/org/connectbot/HostEditorActivity.java
index c0a6229..d5ed0db 100644
--- a/src/org/connectbot/HostEditorActivity.java
+++ b/src/org/connectbot/HostEditorActivity.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -47,15 +47,15 @@ public class HostEditorActivity extends PreferenceActivity implements OnSharedPr
protected Map<String, String> values = new HashMap<String, String>();
// protected Map<String, String> pubkeys = new HashMap<String, String>();
-
+
public CursorPreferenceHack(String table, long id) {
this.table = table;
this.id = id;
-
+
this.cacheValues();
-
+
}
-
+
protected void cacheValues() {
// fill a cursor and cache the values locally
// this makes sure we dont have any floating cursor to dispose later
@@ -64,22 +64,22 @@ public class HostEditorActivity extends PreferenceActivity implements OnSharedPr
Cursor cursor = db.query(table, null, "_id = ?",
new String[] { String.valueOf(id) }, null, null, null);
cursor.moveToFirst();
-
+
for(int i = 0; i < cursor.getColumnCount(); i++) {
String key = cursor.getColumnName(i);
if(key.equals(HostDatabase.FIELD_HOST_HOSTKEY)) continue;
String value = cursor.getString(i);
values.put(key, value);
}
-
+
cursor.close();
db.close();
-
+
// db = pubkeydb.getReadableDatabase();
// cursor = db.query(PubkeyDatabase.TABLE_PUBKEYS,
// new String[] { "_id", PubkeyDatabase.FIELD_PUBKEY_NICKNAME },
// null, null, null, null, null);
-//
+//
// if (cursor.moveToFirst()) {
// do {
// String pubkeyid = String.valueOf(cursor.getLong(0));
@@ -87,19 +87,19 @@ public class HostEditorActivity extends PreferenceActivity implements OnSharedPr
// pubkeys.put(pubkeyid, value);
// } while (cursor.moveToNext());
// }
-//
+//
// cursor.close();
// db.close();
}
-
+
public boolean contains(String key) {
return values.containsKey(key);
}
-
+
public class Editor implements SharedPreferences.Editor {
-
+
private ContentValues update = new ContentValues();
-
+
public SharedPreferences.Editor clear() {
Log.d(this.getClass().toString(), "clear()");
update = new ContentValues();
@@ -111,15 +111,15 @@ public class HostEditorActivity extends PreferenceActivity implements OnSharedPr
SQLiteDatabase db = hostdb.getWritableDatabase();
db.update(table, update, "_id = ?", new String[] { String.valueOf(id) });
db.close();
-
+
// make sure we refresh the parent cached values
cacheValues();
-
+
// and update any listeners
for(OnSharedPreferenceChangeListener listener : listeners) {
listener.onSharedPreferenceChanged(CursorPreferenceHack.this, null);
}
-
+
return true;
}
@@ -150,7 +150,7 @@ public class HostEditorActivity extends PreferenceActivity implements OnSharedPr
update.remove(key);
return this;
}
-
+
}
@@ -181,11 +181,11 @@ public class HostEditorActivity extends PreferenceActivity implements OnSharedPr
public String getString(String key, String defValue) {
//Log.d(this.getClass().toString(), String.format("getString(key=%s, defValue=%s)", key, defValue));
-
+
if(!values.containsKey(key)) return defValue;
return values.get(key);
}
-
+
protected List<OnSharedPreferenceChangeListener> listeners = new LinkedList<OnSharedPreferenceChangeListener>();
public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
@@ -195,77 +195,77 @@ public class HostEditorActivity extends PreferenceActivity implements OnSharedPr
public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
listeners.remove(listener);
}
-
+
}
-
-
+
+
@Override
public SharedPreferences getSharedPreferences(String name, int mode) {
//Log.d(this.getClass().toString(), String.format("getSharedPreferences(name=%s)", name));
return this.pref;
}
-
+
protected HostDatabase hostdb = null;
private PubkeyDatabase pubkeydb = null;
-
+
private CursorPreferenceHack pref;
-
+
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
-
+
long id = this.getIntent().getLongExtra(Intent.EXTRA_TITLE, -1);
-
+
// TODO: we could pass through a specific ContentProvider uri here
//this.getPreferenceManager().setSharedPreferencesName(uri);
-
+
this.hostdb = new HostDatabase(this);
this.pubkeydb = new PubkeyDatabase(this);
-
+
this.pref = new CursorPreferenceHack(HostDatabase.TABLE_HOSTS, id);
this.pref.registerOnSharedPreferenceChangeListener(this);
-
+
this.addPreferencesFromResource(R.xml.host_prefs);
-
+
// add all existing pubkeys to our listpreference for user to choose from
// TODO: may be an issue here when this activity is recycled after adding a new pubkey
// TODO: should consider moving into onStart, but we dont have a good way of resetting the listpref after filling once
ListPreference pubkeyPref = (ListPreference)this.findPreference(HostDatabase.FIELD_HOST_PUBKEYID);
-
+
List<CharSequence> pubkeyNicks = new LinkedList<CharSequence>(Arrays.asList(pubkeyPref.getEntries()));
pubkeyNicks.addAll(pubkeydb.allValues(PubkeyDatabase.FIELD_PUBKEY_NICKNAME));
pubkeyPref.setEntries((CharSequence[]) pubkeyNicks.toArray(new CharSequence[pubkeyNicks.size()]));
-
+
List<CharSequence> pubkeyIds = new LinkedList<CharSequence>(Arrays.asList(pubkeyPref.getEntryValues()));
pubkeyIds.addAll(pubkeydb.allValues("_id"));
pubkeyPref.setEntryValues((CharSequence[]) pubkeyIds.toArray(new CharSequence[pubkeyIds.size()]));
- this.updateSummaries();
+ this.updateSummaries();
}
-
+
public void onStart() {
super.onStart();
if(this.hostdb == null)
this.hostdb = new HostDatabase(this);
-
+
if(this.pubkeydb == null)
this.pubkeydb = new PubkeyDatabase(this);
-
+
}
-
+
public void onStop() {
super.onStop();
if(this.hostdb != null) {
this.hostdb.close();
this.hostdb = null;
}
-
+
if(this.pubkeydb != null) {
this.pubkeydb.close();
this.pubkeydb = null;
}
}
-
+
private void updateSummaries() {
// for all text preferences, set hint as current database value
for(String key : this.pref.values.keySet()) {
@@ -274,7 +274,7 @@ public class HostEditorActivity extends PreferenceActivity implements OnSharedPr
if(pref == null) continue;
if(pref instanceof CheckBoxPreference) continue;
String value = this.pref.getString(key, "");
-
+
if(key.equals("pubkeyid")) {
try {
int pubkeyId = Integer.parseInt(value);
@@ -289,16 +289,16 @@ public class HostEditorActivity extends PreferenceActivity implements OnSharedPr
// Fall through.
}
}
-
+
pref.setSummary(value);
}
-
+
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
// update values on changed preference
this.updateSummaries();
-
+
}
}
diff --git a/src/org/connectbot/HostListActivity.java b/src/org/connectbot/HostListActivity.java
index 1c6a577..1988431 100644
--- a/src/org/connectbot/HostListActivity.java
+++ b/src/org/connectbot/HostListActivity.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -85,11 +85,11 @@ public class HostListActivity extends ListActivity {
private ServiceConnection connection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
bound = ((TerminalManager.TerminalBinder) service).getService();
-
+
// update our listview binder to find the service
HostListActivity.this.updateList();
}
-
+
public void onServiceDisconnected(ComponentName className) {
bound = null;
HostListActivity.this.updateList();
@@ -97,9 +97,9 @@ public class HostListActivity extends ListActivity {
};
@Override
- public void onStart() {
+ public void onStart() {
super.onStart();
-
+
// start the terminal manager service
this.bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE);
@@ -111,20 +111,20 @@ public class HostListActivity extends ListActivity {
}
@Override
- public void onStop() {
+ public void onStop() {
super.onStop();
this.unbindService(connection);
-
+
if(this.hostdb != null) {
this.hostdb.close();
this.hostdb = null;
}
-
+
}
-
-
-
- public final static String PREF_EULA = "eula", PREF_SORTBYCOLOR = "sortByColor";
+
+
+
+ public final static String PREF_EULA = "eula", PREF_SORTBYCOLOR = "sortByColor";
public final static int REQUEST_EDIT = 1;
public final static int REQUEST_EULA = 2;
@@ -146,18 +146,18 @@ public class HostListActivity extends ListActivity {
this.finish();
}
break;
-
+
case REQUEST_EDIT:
this.updateList();
break;
-
+
}
-
+
}
-
-
+
+
protected boolean makingShortcut = false;
-
+
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
@@ -166,24 +166,24 @@ public class HostListActivity extends ListActivity {
this.setTitle(String.format("%s: %s",
getResources().getText(R.string.app_name),
getResources().getText(R.string.title_hosts_list)));
-
+
// check for eula agreement
this.prefs = PreferenceManager.getDefaultSharedPreferences(this);
-
+
boolean agreed = prefs.getBoolean(PREF_EULA, false);
if(!agreed) {
this.startActivityForResult(new Intent(this, WizardActivity.class), REQUEST_EULA);
}
-
+
// start thread to check for new version
new UpdateHelper(this);
-
+
this.makingShortcut = Intent.ACTION_CREATE_SHORTCUT.equals(getIntent().getAction());
// connect with hosts database and populate list
this.hostdb = new HostDatabase(this);
ListView list = this.getListView();
-
+
this.sortedByColor = prefs.getBoolean(PREF_SORTBYCOLOR, false);
this.updateList();
@@ -195,7 +195,7 @@ public class HostListActivity extends ListActivity {
// launch off to console details
HostBean host = (HostBean) parent.getAdapter().getItem(position);
-
+
// create a specific uri that represents this host
Uri uri = Uri.parse(String.format("ssh://%s@%s:%s/#%s",
host.getUsername(), host.getHostname(),
@@ -203,11 +203,11 @@ public class HostListActivity extends ListActivity {
Intent contents = new Intent(Intent.ACTION_VIEW, uri);
contents.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-
+
if (makingShortcut) {
// create shortcut if requested
ShortcutIconResource icon = Intent.ShortcutIconResource.fromContext(HostListActivity.this, R.drawable.icon);
-
+
Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, contents);
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, host.getNickname());
@@ -215,11 +215,11 @@ public class HostListActivity extends ListActivity {
setResult(RESULT_OK, intent);
finish();
-
+
} else {
// otherwise just launch activity to show this host
HostListActivity.this.startActivity(contents);
- }
+ }
}
});
@@ -231,10 +231,10 @@ public class HostListActivity extends ListActivity {
text.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
-
+
if(event.getAction() == KeyEvent.ACTION_UP) return false;
if(keyCode != KeyEvent.KEYCODE_ENTER) return false;
-
+
// make sure we follow pattern
if (text.getText().length() < 3)
return false;
@@ -244,13 +244,13 @@ public class HostListActivity extends ListActivity {
text.setError(getString(R.string.list_format_error));
return false;
}
-
+
// create new host for entered string and then launch
Uri uri = Uri.parse(String.format("ssh://%s", text.getText().toString()));
String username = uri.getUserInfo();
String hostname = uri.getHost();
int port = uri.getPort();
-
+
String nickname;
if(port == -1) {
port = 22;
@@ -258,12 +258,12 @@ public class HostListActivity extends ListActivity {
} else {
nickname = String.format("%s@%s:%d", username, hostname, port);
}
-
+
HostBean host = new HostBean(nickname, username, hostname, port);
host.setColor(HostDatabase.COLOR_GRAY);
host.setPubkeyId(HostDatabase.PUBKEYID_ANY);
hostdb.saveHost(host);
-
+
Intent intent = new Intent(HostListActivity.this, ConsoleActivity.class);
intent.setData(Uri.parse(String.format("ssh://%s@%s:%s/#%s", username, hostname, port, nickname)));
HostListActivity.this.startActivity(intent);
@@ -280,19 +280,19 @@ public class HostListActivity extends ListActivity {
this.inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
-
+
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
-
+
// don't offer menus when creating shortcut
if (makingShortcut) return true;
-
+
sortcolor.setVisible(!sortedByColor);
sortlast.setVisible(sortedByColor);
-
+
return true;
- }
+ }
@Override
public boolean onCreateOptionsMenu(Menu menu) {
@@ -300,7 +300,7 @@ public class HostListActivity extends ListActivity {
// don't offer menus when creating shortcut
if(makingShortcut) return true;
-
+
// add host, ssh keys, about
sortcolor = menu.add(R.string.list_menu_sortcolor);
sortcolor.setIcon(android.R.drawable.ic_menu_share);
@@ -311,7 +311,7 @@ public class HostListActivity extends ListActivity {
return true;
}
});
-
+
sortlast = menu.add(R.string.list_menu_sortname);
sortlast.setIcon(android.R.drawable.ic_menu_share);
sortlast.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@@ -325,7 +325,7 @@ public class HostListActivity extends ListActivity {
MenuItem keys = menu.add(R.string.list_menu_pubkeys);
keys.setIcon(android.R.drawable.ic_lock_lock);
keys.setIntent(new Intent(HostListActivity.this, PubkeyListActivity.class));
-
+
MenuItem settings = menu.add(R.string.list_menu_settings);
settings.setIcon(android.R.drawable.ic_menu_preferences);
settings.setIntent(new Intent(HostListActivity.this, SettingsActivity.class));
@@ -333,11 +333,11 @@ public class HostListActivity extends ListActivity {
MenuItem help = menu.add(R.string.list_menu_help);
help.setIcon(android.R.drawable.ic_menu_help);
help.setIntent(new Intent(HostListActivity.this, HelpActivity.class));
-
+
return true;
-
+
}
-
+
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
@@ -371,7 +371,7 @@ public class HostListActivity extends ListActivity {
return true;
}
});
-
+
MenuItem portForwards = menu.add(R.string.list_host_portforwards);
portForwards.setOnMenuItemClickListener(new OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
@@ -389,32 +389,32 @@ public class HostListActivity extends ListActivity {
new AlertDialog.Builder(HostListActivity.this)
.setMessage(getString(R.string.delete_message, host.getNickname()))
.setPositiveButton(R.string.delete_pos, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- // make sure we disconnect
- if(bridge != null)
- bridge.dispatchDisconnect(true);
+ public void onClick(DialogInterface dialog, int which) {
+ // make sure we disconnect
+ if(bridge != null)
+ bridge.dispatchDisconnect(true);
- hostdb.deleteHost(host);
- updateHandler.sendEmptyMessage(-1);
- }
- })
- .setNegativeButton(R.string.delete_neg, null).create().show();
+ hostdb.deleteHost(host);
+ updateHandler.sendEmptyMessage(-1);
+ }
+ })
+ .setNegativeButton(R.string.delete_neg, null).create().show();
return true;
}
});
}
-
- protected void updateList() {
+
+ protected void updateList() {
Editor edit = prefs.edit();
edit.putBoolean(PREF_SORTBYCOLOR, sortedByColor);
edit.commit();
-
+
if (hostdb == null)
hostdb = new HostDatabase(this);
-
+
hosts = hostdb.getHosts(sortedByColor);
-
+
// Don't lose hosts that are connected via shortcuts but not in the database.
if (bound != null) {
for (TerminalBridge bridge : bound.bridges) {
@@ -424,28 +424,28 @@ public class HostListActivity extends ListActivity {
}
HostAdapter adapter = new HostAdapter(this, hosts, bound);
-
+
this.setListAdapter(adapter);
}
-
+
class HostAdapter extends ArrayAdapter<HostBean> {
private List<HostBean> hosts;
private final TerminalManager manager;
private final ColorStateList red, green, blue;
-
+
public final static int STATE_UNKNOWN = 1, STATE_CONNECTED = 2, STATE_DISCONNECTED = 3;
public HostAdapter(Context context, List<HostBean> hosts, TerminalManager manager) {
super(context, R.layout.item_host, hosts);
-
+
this.hosts = hosts;
this.manager = manager;
-
+
red = context.getResources().getColorStateList(R.color.red);
green = context.getResources().getColorStateList(R.color.green);
blue = context.getResources().getColorStateList(R.color.blue);
}
-
+
/**
* Check if we're connected to a terminal with the given host.
*/
@@ -453,13 +453,13 @@ public class HostListActivity extends ListActivity {
// always disconnected if we dont have backend service
if (this.manager == null)
return STATE_UNKNOWN;
-
+
if (manager.findBridge(host) != null)
return STATE_CONNECTED;
-
+
if (manager.disconnected.contains(host))
return STATE_DISCONNECTED;
-
+
return STATE_UNKNOWN;
}
@@ -475,14 +475,14 @@ public class HostListActivity extends ListActivity {
if (host == null) {
// Well, something bad happened. We can't continue.
Log.e("HostAdapter", "Host bean is null!");
-
+
nickname.setText("Error during lookup");
caption.setText("see 'adb logcat' for more");
return view;
}
-
+
nickname.setText(host.getNickname());
-
+
switch (this.getConnectedState(host)) {
case STATE_UNKNOWN:
icon.setImageState(new int[] { }, true);
@@ -494,7 +494,7 @@ public class HostListActivity extends ListActivity {
icon.setImageState(new int[] { android.R.attr.state_expanded }, true);
break;
}
-
+
ColorStateList chosen = null;
if (HostDatabase.COLOR_RED.equals(host.getColor()))
chosen = this.red;
@@ -502,9 +502,9 @@ public class HostListActivity extends ListActivity {
chosen = this.green;
else if (HostDatabase.COLOR_BLUE.equals(host.getColor()))
chosen = this.blue;
-
+
if (chosen != null) {
- // set color normally if not selected
+ // set color normally if not selected
nickname.setTextColor(chosen);
caption.setTextColor(chosen);
} else {
@@ -512,9 +512,9 @@ public class HostListActivity extends ListActivity {
nickname.setTextAppearance(view.getContext(), android.R.attr.textAppearanceLarge);
caption.setTextAppearance(view.getContext(), android.R.attr.textAppearanceSmall);
}
-
+
long now = System.currentTimeMillis() / 1000;
-
+
String nice = "never";
if (host.getLastConnect() > 0) {
int minutes = (int)((now - host.getLastConnect()) / 60);
@@ -530,7 +530,7 @@ public class HostListActivity extends ListActivity {
}
caption.setText(nice);
-
+
return view;
}
}
diff --git a/src/org/connectbot/PortForwardListActivity.java b/src/org/connectbot/PortForwardListActivity.java
index 81cb2f3..656aa28 100644
--- a/src/org/connectbot/PortForwardListActivity.java
+++ b/src/org/connectbot/PortForwardListActivity.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -59,7 +59,7 @@ import android.widget.AdapterView.OnItemSelectedListener;
/**
* List all portForwards for a particular host and provide a way for users to add more portForwards,
* edit existing portForwards, and delete portForwards.
- *
+ *
* @author Kenny Root
*/
public class PortForwardListActivity extends ListActivity {
@@ -68,27 +68,27 @@ public class PortForwardListActivity extends ListActivity {
protected HostDatabase hostdb;
private List<PortForwardBean> portForwards;
-
+
private ServiceConnection connection = null;
protected TerminalBridge hostBridge = null;
protected LayoutInflater inflater = null;
-
+
private HostBean host;
-
+
@Override
- public void onStart() {
+ public void onStart() {
super.onStart();
-
- this.bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE);
+
+ this.bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE);
if(this.hostdb == null)
this.hostdb = new HostDatabase(this);
}
-
+
@Override
- public void onStop() {
+ public void onStop() {
super.onStop();
-
+
this.unbindService(connection);
if(this.hostdb != null) {
@@ -96,28 +96,28 @@ public class PortForwardListActivity extends ListActivity {
this.hostdb = null;
}
}
-
+
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
-
+
long hostId = this.getIntent().getLongExtra(Intent.EXTRA_TITLE, -1);
setContentView(R.layout.act_portforwardlist);
-
+
// connect with hosts database and populate list
this.hostdb = new HostDatabase(this);
host = hostdb.findHostById(hostId);
-
+
this.setTitle(String.format("%s: %s (%s)",
getResources().getText(R.string.app_name),
- getResources().getText(R.string.title_port_forwards_list),
+ getResources().getText(R.string.title_port_forwards_list),
host.getNickname()));
-
+
connection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
TerminalManager bound = ((TerminalManager.TerminalBinder) service).getService();
-
+
for (TerminalBridge bridge: bound.bridges) {
if (bridge.host.equals(host)) {
hostBridge = bridge;
@@ -126,44 +126,44 @@ public class PortForwardListActivity extends ListActivity {
break;
}
}
-
-
+
+
}
public void onServiceDisconnected(ComponentName name) {
hostBridge = null;
}
};
-
+
this.updateList();
-
+
this.registerForContextMenu(this.getListView());
-
+
this.getListView().setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> adapter, View view, int position, long id) {
ListView lv = PortForwardListActivity.this.getListView();
PortForwardBean pfb = (PortForwardBean) lv.getItemAtPosition(position);
-
+
if (hostBridge != null) {
if (pfb.isEnabled())
hostBridge.disablePortForward(pfb);
else {
if (!hostBridge.enablePortForward(pfb))
- Toast.makeText(PortForwardListActivity.this, getString(R.string.portforward_problem), Toast.LENGTH_LONG).show();
+ Toast.makeText(PortForwardListActivity.this, getString(R.string.portforward_problem), Toast.LENGTH_LONG).show();
}
updateHandler.sendEmptyMessage(-1);
}
}
});
-
+
this.inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
-
+
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
-
+
MenuItem add = menu.add(R.string.portforward_menu_add);
add.setIcon(android.R.drawable.ic_menu_add);
add.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@@ -172,16 +172,16 @@ public class PortForwardListActivity extends ListActivity {
final View portForwardView = inflater.inflate(R.layout.dia_portforward, null, false);
final EditText destEdit = (EditText) portForwardView.findViewById(R.id.portforward_destination);
final Spinner typeSpinner = (Spinner)portForwardView.findViewById(R.id.portforward_type);
-
+
typeSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> value, View view,
int position, long id) {
destEdit.setEnabled(position != 2);
}
- public void onNothingSelected(AdapterView<?> arg0) {
- }
+ public void onNothingSelected(AdapterView<?> arg0) {
+ }
});
-
+
new AlertDialog.Builder(PortForwardListActivity.this)
.setView(portForwardView)
.setPositiveButton(R.string.portforward_pos, new DialogInterface.OnClickListener() {
@@ -202,20 +202,20 @@ public class PortForwardListActivity extends ListActivity {
type = HostDatabase.PORTFORWARD_DYNAMIC5;
break;
}
-
+
PortForwardBean pfb = new PortForwardBean(host.getId(),
nicknameEdit.getText().toString(), type,
sourcePortEdit.getText().toString(),
destEdit.getText().toString());
-
+
if (hostBridge != null) {
hostBridge.addPortForward(pfb);
hostBridge.enablePortForward(pfb);
}
-
+
if (!hostdb.savePortForward(pfb))
throw new Exception("Could not save port forward");
-
+
updateHandler.sendEmptyMessage(-1);
} catch (Exception e) {
Log.e(TAG, "Could not update port forward", e);
@@ -224,14 +224,14 @@ public class PortForwardListActivity extends ListActivity {
}
})
.setNegativeButton(R.string.portforward_neg, null).create().show();
-
+
return true;
}
});
-
+
return true;
}
-
+
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
// Create menu to handle deleting and editing port forward
@@ -239,12 +239,12 @@ public class PortForwardListActivity extends ListActivity {
final PortForwardBean pfb = (PortForwardBean) this.getListView().getItemAtPosition(info.position);
menu.setHeaderTitle(pfb.getNickname());
-
+
MenuItem edit = menu.add(R.string.portforward_edit);
edit.setOnMenuItemClickListener(new OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
final View editTunnelView = inflater.inflate(R.layout.dia_portforward, null, false);
-
+
final Spinner typeSpinner = (Spinner) editTunnelView.findViewById(R.id.portforward_type);
if (HostDatabase.PORTFORWARD_LOCAL.equals(pfb.getType()))
typeSpinner.setSelection(0);
@@ -258,30 +258,30 @@ public class PortForwardListActivity extends ListActivity {
final EditText sourcePortEdit = (EditText) editTunnelView.findViewById(R.id.portforward_source);
sourcePortEdit.setText(String.valueOf(pfb.getSourcePort()));
-
+
final EditText destEdit = (EditText) editTunnelView.findViewById(R.id.portforward_destination);
if (HostDatabase.PORTFORWARD_DYNAMIC5.equals(pfb.getType())) {
destEdit.setEnabled(false);
} else {
destEdit.setText(String.format("%s:%d", pfb.getDestAddr(), pfb.getDestPort()));
}
-
+
typeSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> value, View view,
int position, long id) {
destEdit.setEnabled(position != 2);
}
- public void onNothingSelected(AdapterView<?> arg0) {
- }
+ public void onNothingSelected(AdapterView<?> arg0) {
+ }
});
-
+
new AlertDialog.Builder(PortForwardListActivity.this)
.setView(editTunnelView)
.setPositiveButton(R.string.button_change, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
try {
pfb.setNickname(nicknameEdit.getText().toString());
-
+
switch (typeSpinner.getSelectedItemPosition()) {
case 0:
pfb.setType(HostDatabase.PORTFORWARD_LOCAL);
@@ -293,19 +293,19 @@ public class PortForwardListActivity extends ListActivity {
pfb.setType(HostDatabase.PORTFORWARD_DYNAMIC5);
break;
}
-
+
pfb.setSourcePort(Integer.parseInt(sourcePortEdit.getText().toString()));
pfb.setDest(destEdit.getText().toString());
-
+
// Use the new settings for the existing connection.
if (hostBridge != null) {
hostBridge.disablePortForward(pfb);
hostBridge.enablePortForward(pfb);
}
-
+
if (!hostdb.savePortForward(pfb))
throw new Exception("Could not save port forward");
-
+
updateHandler.sendEmptyMessage(-1);
} catch (Exception e) {
Log.e(TAG, "Could not update port forward", e);
@@ -314,11 +314,11 @@ public class PortForwardListActivity extends ListActivity {
}
})
.setNegativeButton(android.R.string.cancel, null).create().show();
-
+
return true;
}
});
-
+
MenuItem delete = menu.add(R.string.portforward_delete);
delete.setOnMenuItemClickListener(new OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
@@ -326,35 +326,35 @@ public class PortForwardListActivity extends ListActivity {
new AlertDialog.Builder(PortForwardListActivity.this)
.setMessage(getString(R.string.delete_message, pfb.getNickname()))
.setPositiveButton(R.string.delete_pos, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- try {
- // Delete the port forward from the host if needed.
- if (hostBridge != null)
- hostBridge.removePortForward(pfb);
-
- hostdb.deletePortForward(pfb);
- } catch (Exception e) {
- Log.e(TAG, "Could not delete port forward", e);
- }
-
- updateHandler.sendEmptyMessage(-1);
- }
- })
- .setNegativeButton(R.string.delete_neg, null).create().show();
-
+ public void onClick(DialogInterface dialog, int which) {
+ try {
+ // Delete the port forward from the host if needed.
+ if (hostBridge != null)
+ hostBridge.removePortForward(pfb);
+
+ hostdb.deletePortForward(pfb);
+ } catch (Exception e) {
+ Log.e(TAG, "Could not delete port forward", e);
+ }
+
+ updateHandler.sendEmptyMessage(-1);
+ }
+ })
+ .setNegativeButton(R.string.delete_neg, null).create().show();
+
return true;
}
});
}
-
+
protected Handler updateHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
PortForwardListActivity.this.updateList();
}
};
-
- protected void updateList() {
+
+ protected void updateList() {
if (hostBridge != null) {
this.portForwards = hostBridge.getPortForwards();
} else {
@@ -363,16 +363,16 @@ public class PortForwardListActivity extends ListActivity {
}
PortForwardAdapter adapter = new PortForwardAdapter(this, portForwards);
-
+
this.setListAdapter(adapter);
}
-
+
class PortForwardAdapter extends ArrayAdapter<PortForwardBean> {
private List<PortForwardBean> portForwards;
public PortForwardAdapter(Context context, List<PortForwardBean> portForwards) {
super(context, R.layout.item_portforward, portForwards);
-
+
this.portForwards = portForwards;
}
@@ -386,12 +386,12 @@ public class PortForwardListActivity extends ListActivity {
PortForwardBean pfb = portForwards.get(position);
nickname.setText(pfb.getNickname());
caption.setText(pfb.getDescription());
-
+
if (hostBridge != null && !pfb.isEnabled()) {
nickname.setPaintFlags(nickname.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
caption.setPaintFlags(caption.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
}
-
+
return view;
}
}
diff --git a/src/org/connectbot/PubkeyListActivity.java b/src/org/connectbot/PubkeyListActivity.java
index aa02a16..8e89a89 100644
--- a/src/org/connectbot/PubkeyListActivity.java
+++ b/src/org/connectbot/PubkeyListActivity.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -74,7 +74,7 @@ import com.trilead.ssh2.crypto.PEMStructure;
/**
* List public keys in database by nickname and describe their properties. Allow users to import,
* generate, rename, and delete key pairs.
- *
+ *
* @author Kenny Root
*/
public class PubkeyListActivity extends ListActivity implements EventListener {
@@ -82,13 +82,13 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
protected PubkeyDatabase pubkeydb;
private List<PubkeyBean> pubkeys;
-
+
protected ClipboardManager clipboard;
-
+
protected LayoutInflater inflater = null;
-
+
protected TerminalManager bound = null;
-
+
private MenuItem onstartToggle = null;
private ServiceConnection connection = new ServiceConnection() {
@@ -106,19 +106,19 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
};
@Override
- public void onStart() {
+ public void onStart() {
super.onStart();
-
+
bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE);
if(pubkeydb == null)
pubkeydb = new PubkeyDatabase(this);
}
-
+
@Override
- public void onStop() {
+ public void onStop() {
super.onStop();
-
+
unbindService(connection);
if(pubkeydb != null) {
@@ -126,28 +126,28 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
pubkeydb = null;
}
}
-
+
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.act_pubkeylist);
-
+
this.setTitle(String.format("%s: %s",
getResources().getText(R.string.app_name),
getResources().getText(R.string.title_pubkey_list)));
-
+
// connect with hosts database and populate list
pubkeydb = new PubkeyDatabase(this);
-
+
updateList();
-
+
registerForContextMenu(getListView());
-
+
getListView().setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> adapter, View view, int position, long id) {
PubkeyBean pubkey = (PubkeyBean) getListView().getItemAtPosition(position);
boolean loaded = bound.isKeyLoaded(pubkey.getNickname());
-
+
// handle toggling key in-memory on/off
if(loaded) {
bound.removeKey(pubkey.getNickname());
@@ -158,19 +158,19 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
}
});
-
+
clipboard = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE);
-
+
inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
-
+
/**
* Read given file into memory as <code>byte[]</code>.
*/
protected static byte[] readRaw(File file) throws Exception {
InputStream is = new FileInputStream(file);
ByteArrayOutputStream os = new ByteArrayOutputStream();
-
+
int bytesRead;
byte[] buffer = new byte[1024];
while ((bytesRead = is.read(buffer)) != -1) {
@@ -182,13 +182,13 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
is.close();
return os.toByteArray();
-
+
}
-
+
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
-
+
MenuItem generatekey = menu.add(R.string.pubkey_generate);
generatekey.setIcon(android.R.drawable.ic_menu_manage);
generatekey.setIntent(new Intent(PubkeyListActivity.this, GeneratePubkeyActivity.class));
@@ -197,14 +197,14 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
importkey.setIcon(android.R.drawable.ic_menu_upload);
importkey.setOnMenuItemClickListener(new OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
-
+
// TODO: replace this with well-known intent over to file browser
// TODO: if browser not installed (?) then fallback to this simple method?
-
+
// build list of all files in sdcard root
final File sdcard = Environment.getExternalStorageDirectory();
Log.d(TAG, sdcard.toString());
-
+
// Don't show a dialog if the SD card is completely absent.
final String state = Environment.getExternalStorageState();
if (Environment.MEDIA_REMOVED.equals(state)
@@ -216,14 +216,14 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
.setNegativeButton(android.R.string.cancel, null).create().show();
return true;
}
-
+
List<String> names = new LinkedList<String>();
for(File file : sdcard.listFiles()) {
if(file.isDirectory()) continue;
names.add(file.getName());
}
Collections.sort(names);
-
+
final String[] namesList = names.toArray(new String[] {});
Log.d(TAG, names.toString());
@@ -238,24 +238,24 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
String name = namesList[arg1];
pubkey.setNickname(name);
File actual = new File(sdcard, name);
-
+
// parse the actual key once to check if its encrypted
// then save original file contents into our database
try {
byte[] raw = readRaw(actual);
-
+
String data = new String(raw);
if (data.startsWith(PubkeyUtils.PKCS8_START)) {
int start = data.indexOf(PubkeyUtils.PKCS8_START) + PubkeyUtils.PKCS8_START.length();
int end = data.indexOf(PubkeyUtils.PKCS8_END);
-
+
if (end > start) {
char[] encoded = data.substring(start, end - 1).toCharArray();
Log.d(TAG, "encoded: " + new String(encoded));
byte[] decoded = Base64.decode(encoded);
-
+
KeyPair kp = PubkeyUtils.recoverKeyPair(decoded);
-
+
pubkey.setType(kp.getPrivate().getAlgorithm());
pubkey.setPrivateKey(kp.getPrivate().getEncoded());
pubkey.setPublicKey(kp.getPublic().getEncoded());
@@ -271,7 +271,7 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
pubkey.setType(PubkeyDatabase.KEY_TYPE_IMPORTED);
pubkey.setPrivateKey(raw);
}
-
+
// write new value into database
pubkeydb.savePubkey(pubkey);
updateHandler.sendEmptyMessage(-1);
@@ -286,28 +286,28 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
return true;
}
});
-
+
return true;
}
-
- protected void handleAddKey(final PubkeyBean pubkey) {
+
+ protected void handleAddKey(final PubkeyBean pubkey) {
if (pubkey.isEncrypted()) {
final View view = inflater.inflate(R.layout.dia_password, null);
final EditText passwordField = (EditText)view.findViewById(android.R.id.text1);
-
+
new AlertDialog.Builder(PubkeyListActivity.this)
.setView(view)
.setPositiveButton(R.string.pubkey_unlock, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- handleAddKey(pubkey, passwordField.getText().toString());
- }
- })
- .setNegativeButton(android.R.string.cancel, null).create().show();
+ public void onClick(DialogInterface dialog, int which) {
+ handleAddKey(pubkey, passwordField.getText().toString());
+ }
+ })
+ .setNegativeButton(android.R.string.cancel, null).create().show();
} else {
handleAddKey(pubkey, null);
}
}
-
+
protected void handleAddKey(PubkeyBean pubkey, String password) {
Object trileadKey = null;
if(PubkeyDatabase.KEY_TYPE_IMPORTED.equals(pubkey.getType())) {
@@ -319,7 +319,7 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
Log.e(TAG, message, e);
Toast.makeText(PubkeyListActivity.this, message, Toast.LENGTH_LONG);
}
-
+
} else {
// load using internal generated format
PrivateKey privKey = null;
@@ -340,17 +340,17 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
}
if(trileadKey == null) return;
-
+
Log.d(TAG, String.format("Unlocked key '%s'", pubkey.getNickname()));
// save this key in-memory if option enabled
if(bound.isSavingKeys()) {
bound.addKey(pubkey.getNickname(), trileadKey);
}
-
+
updateHandler.sendEmptyMessage(-1);
}
-
+
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
// Create menu to handle deleting and editing pubkey
@@ -358,10 +358,10 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
final PubkeyBean pubkey = (PubkeyBean) getListView().getItemAtPosition(info.position);
menu.setHeaderTitle(pubkey.getNickname());
-
+
// TODO: option load/unload key from in-memory list
// prompt for password as needed for passworded keys
-
+
// cant change password or clipboard imported keys
final boolean imported = PubkeyDatabase.KEY_TYPE_IMPORTED.equals(pubkey.getType());
final boolean loaded = bound.isKeyLoaded(pubkey.getNickname());
@@ -379,7 +379,7 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
return true;
}
});
-
+
onstartToggle = menu.add(R.string.pubkey_load_on_start);
onstartToggle.setEnabled(!pubkey.isEncrypted());
onstartToggle.setCheckable(true);
@@ -409,21 +409,21 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
return true;
}
});
-
- MenuItem copyPrivateToClipboard = menu.add(R.string.pubkey_copy_private);
- copyPrivateToClipboard.setEnabled(!pubkey.isEncrypted() || imported);
+
+ MenuItem copyPrivateToClipboard = menu.add(R.string.pubkey_copy_private);
+ copyPrivateToClipboard.setEnabled(!pubkey.isEncrypted() || imported);
copyPrivateToClipboard.setOnMenuItemClickListener(new OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
try {
String data = null;
-
+
if (imported)
data = new String(pubkey.getPrivateKey());
else {
PrivateKey pk = PubkeyUtils.decodePrivate(pubkey.getPrivateKey(), pubkey.getType());
data = PubkeyUtils.exportPEM(pk, null);
}
-
+
clipboard.setText(data);
} catch (Exception e) {
e.printStackTrace();
@@ -431,7 +431,7 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
return true;
}
});
-
+
MenuItem changePassword = menu.add(R.string.pubkey_change_password);
changePassword.setEnabled(!imported);
changePassword.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@@ -446,7 +446,7 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
String oldPassword = ((EditText)changePasswordView.findViewById(R.id.old_password)).getText().toString();
String password1 = ((EditText)changePasswordView.findViewById(R.id.password1)).getText().toString();
String password2 = ((EditText)changePasswordView.findViewById(R.id.password2)).getText().toString();
-
+
if (!password1.equals(password2)) {
new AlertDialog.Builder(PubkeyListActivity.this)
.setMessage(R.string.alert_passwords_do_not_match_msg)
@@ -454,7 +454,7 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
.create().show();
return;
}
-
+
try {
if (!pubkey.changePassword(oldPassword, password1))
new AlertDialog.Builder(PubkeyListActivity.this)
@@ -475,11 +475,11 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
}
})
.setNegativeButton(android.R.string.cancel, null).create().show();
-
+
return true;
}
});
-
+
MenuItem delete = menu.add(R.string.pubkey_delete);
delete.setOnMenuItemClickListener(new OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
@@ -487,25 +487,25 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
new AlertDialog.Builder(PubkeyListActivity.this)
.setMessage(getString(R.string.delete_message, pubkey.getNickname()))
.setPositiveButton(R.string.delete_pos, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
-
- // dont forget to remove from in-memory
- if(loaded)
- bound.removeKey(pubkey.getNickname());
-
- // delete from backend database and update gui
- pubkeydb.deletePubkey(pubkey);
- updateHandler.sendEmptyMessage(-1);
- }
- })
- .setNegativeButton(R.string.delete_neg, null).create().show();
+ public void onClick(DialogInterface dialog, int which) {
+
+ // dont forget to remove from in-memory
+ if(loaded)
+ bound.removeKey(pubkey.getNickname());
+
+ // delete from backend database and update gui
+ pubkeydb.deletePubkey(pubkey);
+ updateHandler.sendEmptyMessage(-1);
+ }
+ })
+ .setNegativeButton(R.string.delete_neg, null).create().show();
return true;
}
});
-
+
}
-
+
protected Handler updateHandler = new Handler() {
@Override
@@ -513,22 +513,22 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
updateList();
}
};
-
+
protected void updateList() {
if (pubkeydb == null) return;
-
+
pubkeys = pubkeydb.allPubkeys();
PubkeyAdapter adapter = new PubkeyAdapter(this, pubkeys);
-
+
this.setListAdapter(adapter);
}
-
+
class PubkeyAdapter extends ArrayAdapter<PubkeyBean> {
private List<PubkeyBean> pubkeys;
public PubkeyAdapter(Context context, List<PubkeyBean> pubkeys) {
super(context, R.layout.item_pubkey, pubkeys);
-
+
this.pubkeys = pubkeys;
}
@@ -542,7 +542,7 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
PubkeyBean pubkey = pubkeys.get(position);
nickname.setText(pubkey.getNickname());
-
+
boolean imported = PubkeyDatabase.KEY_TYPE_IMPORTED.equals(pubkey.getType());
if (imported) {
@@ -562,18 +562,18 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
caption.setText(R.string.pubkey_unknown_format);
}
}
-
+
if (bound == null) {
icon.setVisibility(View.GONE);
} else {
icon.setVisibility(View.VISIBLE);
-
+
if (bound.isKeyLoaded(pubkey.getNickname()))
icon.setImageState(new int[] { android.R.attr.state_checked }, true);
else
icon.setImageState(new int[] { }, true);
}
-
+
return view;
}
}
diff --git a/src/org/connectbot/SettingsActivity.java b/src/org/connectbot/SettingsActivity.java
index 8c31c5b..422e1df 100644
--- a/src/org/connectbot/SettingsActivity.java
+++ b/src/org/connectbot/SettingsActivity.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
diff --git a/src/org/connectbot/TerminalView.java b/src/org/connectbot/TerminalView.java
index 3feebd5..067d54b 100644
--- a/src/org/connectbot/TerminalView.java
+++ b/src/org/connectbot/TerminalView.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -34,7 +34,7 @@ import android.widget.Toast;
* User interface {@link View} for showing a TerminalBridge in an
* {@link Activity}. Handles drawing bitmap updates and passing keystrokes down
* to terminal.
- *
+ *
* @author jsharkey
*/
public class TerminalView extends View {
@@ -43,63 +43,63 @@ public class TerminalView extends View {
public final TerminalBridge bridge;
private final Paint paint;
private final Paint cursorPaint;
-
+
private Toast notification = null;
private String lastNotification = null;
public TerminalView(Context context, TerminalBridge bridge) {
super(context);
-
+
this.context = context;
this.bridge = bridge;
paint = new Paint();
-
+
setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
setFocusable(true);
setFocusableInTouchMode(true);
-
+
cursorPaint = new Paint();
cursorPaint.setColor(bridge.color[TerminalBridge.COLOR_FG_STD]);
cursorPaint.setXfermode(new PixelXorXfermode(bridge.color[TerminalBridge.COLOR_BG_STD]));
-
+
// connect our view up to the bridge
setOnKeyListener(bridge);
-
-
+
+
}
-
+
public void destroy() {
// tell bridge to destroy its bitmap
bridge.parentDestroyed();
}
-
+
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
bridge.parentChanged(this);
}
-
+
@Override
public void onDraw(Canvas canvas) {
if(bridge.bitmap != null) {
// draw the bitmap
bridge.onDraw();
-
+
// draw the bridge bitmap if it exists
canvas.drawBitmap(bridge.bitmap, 0, 0, paint);
-
+
// also draw cursor if visible
if(bridge.buffer.isCursorVisible()) {
int x = bridge.buffer.getCursorColumn() * bridge.charWidth;
int y = (bridge.buffer.getCursorRow()
+ bridge.buffer.screenBase - bridge.buffer.windowBase)
* bridge.charHeight;
-
+
canvas.drawRect(x, y, x + bridge.charWidth,
y + bridge.charHeight, cursorPaint);
-
+
}
-
+
// draw any highlighted area
if (bridge.isSelectingForCopy()) {
SelectionArea area = bridge.getSelectionArea();
@@ -113,20 +113,20 @@ public class TerminalView extends View {
}
}
}
-
+
public void notifyUser(String message) {
if (notification != null) {
// Don't keep telling the user the same thing.
if (lastNotification != null && lastNotification.equals(message))
return;
-
+
notification.setText(message);
notification.show();
} else {
notification = Toast.makeText(context, message, Toast.LENGTH_SHORT);
notification.show();
}
-
+
lastNotification = message;
}
diff --git a/src/org/connectbot/WizardActivity.java b/src/org/connectbot/WizardActivity.java
index abfcdd5..9e76ba0 100644
--- a/src/org/connectbot/WizardActivity.java
+++ b/src/org/connectbot/WizardActivity.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -32,20 +32,20 @@ import android.widget.ViewFlipper;
/**
* Show a series of wizard-like steps to the user, which might include an EULA,
* program credits, and helpful hints.
- *
+ *
* @author jsharkey
*/
public class WizardActivity extends Activity {
protected ViewFlipper flipper = null;
private Button next, prev;
-
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_wizard);
-
+
this.flipper = (ViewFlipper) findViewById(R.id.wizard_flipper);
-
+
// inflate the layout for EULA step
LayoutInflater inflater = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.flipper.addView(inflater.inflate(R.layout.wiz_eula, this.flipper, false));
@@ -55,7 +55,7 @@ public class WizardActivity extends Activity {
for (String topic : topics) {
flipper.addView(new HelpTopicView(this).setTopic(topic));
}
-
+
next = (Button)this.findViewById(R.id.action_next);
next.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
@@ -70,7 +70,7 @@ public class WizardActivity extends Activity {
}
}
});
-
+
prev = (Button)this.findViewById(R.id.action_prev);
prev.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
@@ -85,21 +85,21 @@ public class WizardActivity extends Activity {
}
}
});
-
- this.updateButtons();
+
+ this.updateButtons();
}
-
+
protected boolean isFirstDisplayed() {
return (flipper.getDisplayedChild() == 0);
}
-
+
protected boolean isLastDisplayed() {
return (flipper.getDisplayedChild() == flipper.getChildCount() - 1);
}
-
+
protected void updateButtons() {
boolean eula = (flipper.getDisplayedChild() == 0);
-
+
next.setText(eula ? getString(R.string.wizard_agree) : getString(R.string.wizard_next));
prev.setText(eula ? getString(R.string.wizard_cancel) : getString(R.string.wizard_back));
}
diff --git a/src/org/connectbot/bean/AbstractBean.java b/src/org/connectbot/bean/AbstractBean.java
index 4998727..da5991a 100644
--- a/src/org/connectbot/bean/AbstractBean.java
+++ b/src/org/connectbot/bean/AbstractBean.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -30,10 +30,10 @@ import android.content.ContentValues;
abstract class AbstractBean {
public abstract ContentValues getValues();
public abstract String getBeanName();
-
+
public String toXML() {
XmlBuilder xml = new XmlBuilder();
-
+
xml.append(String.format("<%s>", getBeanName()));
ContentValues values = getValues();
@@ -43,7 +43,7 @@ abstract class AbstractBean {
xml.append(entry.getKey(), value);
}
xml.append(String.format("</%s>", getBeanName()));
-
+
return xml.toString();
}
}
diff --git a/src/org/connectbot/bean/HostBean.java b/src/org/connectbot/bean/HostBean.java
index bd8f424..fbde26f 100644
--- a/src/org/connectbot/bean/HostBean.java
+++ b/src/org/connectbot/bean/HostBean.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -27,7 +27,7 @@ import android.content.ContentValues;
*/
public class HostBean extends AbstractBean {
public static final String BEAN_NAME = "host";
-
+
/* Database fields */
private long id = -1;
private String nickname = null;
@@ -46,20 +46,20 @@ public class HostBean extends AbstractBean {
private String encoding = HostDatabase.ENCODING_ASCII;
public HostBean() {
-
+
}
-
+
public String getBeanName() {
return BEAN_NAME;
}
-
+
public HostBean(String nickname, String username, String hostname, int port) {
this.nickname = nickname;
this.username = username;
this.hostname = hostname;
this.port = port;
}
-
+
public void setId(long id) {
this.id = id;
}
@@ -158,19 +158,19 @@ public class HostBean extends AbstractBean {
public String getEncoding() {
return this.encoding;
}
-
+
public String getDescription() {
String description = String.format("%s@%s", username, hostname);
-
+
if (port != 22)
description += String.format(":%d", port);
-
+
return description;
}
-
+
public ContentValues getValues() {
ContentValues values = new ContentValues();
-
+
values.put(HostDatabase.FIELD_HOST_NICKNAME, nickname);
values.put(HostDatabase.FIELD_HOST_USERNAME, username);
values.put(HostDatabase.FIELD_HOST_HOSTNAME, hostname);
@@ -185,36 +185,36 @@ public class HostBean extends AbstractBean {
values.put(HostDatabase.FIELD_HOST_WANTSESSION, Boolean.toString(wantSession));
values.put(HostDatabase.FIELD_HOST_COMPRESSION, Boolean.toString(compression));
values.put(HostDatabase.FIELD_HOST_ENCODING, encoding);
-
+
return values;
}
-
+
@Override
public boolean equals(Object o) {
if (!(o instanceof HostBean))
return false;
-
+
HostBean host = (HostBean)o;
-
+
if (host.getNickname().equals(nickname)
&& host.getUsername().equals(username)
&& host.getHostname().equals(hostname)
&& host.getPort() == port)
return true;
-
+
return false;
}
@Override
public int hashCode() {
int hash = 7;
-
+
hash = 31 * hash + (null == nickname ? 0 : nickname.hashCode());
hash = 31 * hash + (null == username ? 0 : username.hashCode());
hash = 31 * hash + (null == hostname ? 0 : hostname.hashCode());
hash = 31 * hash + port;
-
+
return hash;
}
-
+
}
diff --git a/src/org/connectbot/bean/PortForwardBean.java b/src/org/connectbot/bean/PortForwardBean.java
index 9a2036f..d497d2c 100644
--- a/src/org/connectbot/bean/PortForwardBean.java
+++ b/src/org/connectbot/bean/PortForwardBean.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -28,7 +28,7 @@ import android.content.ContentValues;
*/
public class PortForwardBean extends AbstractBean {
public static final String BEAN_NAME = "portforward";
-
+
/* Database fields */
private long id = -1;
private long hostId = -1;
@@ -37,11 +37,11 @@ public class PortForwardBean extends AbstractBean {
private int sourcePort = -1;
private String destAddr = null;
private int destPort = -1;
-
+
/* Transient values */
private boolean enabled = false;
private Object identifier = null;
-
+
/**
* @param id database ID of port forward
* @param nickname Nickname to use to identify port forward
@@ -59,7 +59,7 @@ public class PortForwardBean extends AbstractBean {
this.destAddr = destAddr;
this.destPort = destPort;
}
-
+
/**
* @param type One of the port forward types from {@link HostDatabase}
* @param source Source port number
@@ -70,28 +70,28 @@ public class PortForwardBean extends AbstractBean {
this.nickname = nickname;
this.type = type;
this.sourcePort = Integer.parseInt(source);
-
+
this.setDest(dest);
}
public String getBeanName() {
return BEAN_NAME;
}
-
+
/**
* @param id the id to set
*/
public void setId(long id) {
this.id = id;
}
-
+
/**
* @return the id
*/
public long getId() {
return id;
}
-
+
/**
* @param nickname the nickname to set
*/
@@ -112,28 +112,28 @@ public class PortForwardBean extends AbstractBean {
public void setType(String type) {
this.type = type;
}
-
+
/**
* @return the type
*/
public String getType() {
return type;
}
-
+
/**
* @param sourcePort the sourcePort to set
*/
public void setSourcePort(int sourcePort) {
this.sourcePort = sourcePort;
}
-
+
/**
* @return the sourcePort
*/
public int getSourcePort() {
return sourcePort;
}
-
+
/**
* @param dest The destination in "host:port" format
*/
@@ -143,42 +143,42 @@ public class PortForwardBean extends AbstractBean {
if (destSplit.length > 1)
this.destPort = Integer.parseInt(destSplit[1]);
}
-
+
/**
* @param destAddr the destAddr to set
*/
public void setDestAddr(String destAddr) {
this.destAddr = destAddr;
}
-
+
/**
* @return the destAddr
*/
public String getDestAddr() {
return destAddr;
}
-
+
/**
* @param destPort the destPort to set
*/
public void setDestPort(int destPort) {
this.destPort = destPort;
}
-
+
/**
* @return the destPort
*/
public int getDestPort() {
return destPort;
}
-
+
/**
* @param enabled the enabled to set
*/
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
-
+
/**
* @return the enabled
*/
@@ -205,11 +205,11 @@ public class PortForwardBean extends AbstractBean {
*/
public CharSequence getDescription() {
String description = "Unknown type";
-
+
if (HostDatabase.PORTFORWARD_LOCAL.equals(type)) {
description = String.format("Local port %d to %s:%d", sourcePort, destAddr, destPort);
} else if (HostDatabase.PORTFORWARD_REMOTE.equals(type)) {
- description = String.format("Remote port %d to %s:%d", sourcePort, destAddr, destPort);
+ description = String.format("Remote port %d to %s:%d", sourcePort, destAddr, destPort);
/* I don't think we need the SOCKS4 type.
} else if (HostDatabase.PORTFORWARD_DYNAMIC4.equals(type)) {
description = String.format("Dynamic port %d (SOCKS4)", sourcePort);
@@ -217,7 +217,7 @@ public class PortForwardBean extends AbstractBean {
} else if (HostDatabase.PORTFORWARD_DYNAMIC5.equals(type)) {
description = String.format("Dynamic port %d (SOCKS)", sourcePort);
}
-
+
return description;
}
@@ -226,14 +226,14 @@ public class PortForwardBean extends AbstractBean {
*/
public ContentValues getValues() {
ContentValues values = new ContentValues();
-
+
values.put(HostDatabase.FIELD_PORTFORWARD_HOSTID, hostId);
values.put(HostDatabase.FIELD_PORTFORWARD_NICKNAME, nickname);
values.put(HostDatabase.FIELD_PORTFORWARD_TYPE, type);
values.put(HostDatabase.FIELD_PORTFORWARD_SOURCEPORT, sourcePort);
values.put(HostDatabase.FIELD_PORTFORWARD_DESTADDR, destAddr);
values.put(HostDatabase.FIELD_PORTFORWARD_DESTPORT, destPort);
-
+
return values;
}
}
diff --git a/src/org/connectbot/bean/PubkeyBean.java b/src/org/connectbot/bean/PubkeyBean.java
index c103a07..522369d 100644
--- a/src/org/connectbot/bean/PubkeyBean.java
+++ b/src/org/connectbot/bean/PubkeyBean.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -30,7 +30,7 @@ import android.content.ContentValues;
*/
public class PubkeyBean extends AbstractBean {
public static final String BEAN_NAME = "pubkey";
-
+
/* Database fields */
private long id;
private String nickname;
@@ -39,15 +39,15 @@ public class PubkeyBean extends AbstractBean {
private byte[] publicKey;
private boolean encrypted = false;
private boolean startup = false;
-
+
/* Transient values */
private boolean unlocked = false;
private Object unlockedPrivate = null;
-
+
public String getBeanName() {
return BEAN_NAME;
}
-
+
public void setId(long id) {
this.id = id;
}
@@ -138,29 +138,29 @@ public class PubkeyBean extends AbstractBean {
@Override
public ContentValues getValues() {
ContentValues values = new ContentValues();
-
+
values.put(PubkeyDatabase.FIELD_PUBKEY_NICKNAME, nickname);
values.put(PubkeyDatabase.FIELD_PUBKEY_TYPE, type);
values.put(PubkeyDatabase.FIELD_PUBKEY_PRIVATE, privateKey);
values.put(PubkeyDatabase.FIELD_PUBKEY_PUBLIC, publicKey);
values.put(PubkeyDatabase.FIELD_PUBKEY_ENCRYPTED, encrypted ? 1 : 0);
values.put(PubkeyDatabase.FIELD_PUBKEY_STARTUP, startup ? 1 : 0);
-
+
return values;
}
public boolean changePassword(String oldPassword, String newPassword) throws Exception {
PrivateKey priv;
-
+
try {
priv = PubkeyUtils.decodePrivate(getPrivateKey(), getType(), oldPassword);
} catch (Exception e) {
return false;
}
-
+
setPrivateKey(PubkeyUtils.getEncodedPrivate(priv, newPassword));
setEncrypted(newPassword.length() > 0);
-
+
return true;
}
}
diff --git a/src/org/connectbot/bean/SelectionArea.java b/src/org/connectbot/bean/SelectionArea.java
index 6f13193..6cb7f4c 100644
--- a/src/org/connectbot/bean/SelectionArea.java
+++ b/src/org/connectbot/bean/SelectionArea.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -33,16 +33,16 @@ public class SelectionArea {
private int maxColumns;
private int maxRows;
private boolean selectingOrigin;
-
+
public SelectionArea() {
reset();
}
-
+
public void reset() {
top = left = bottom = right = 0;
selectingOrigin = true;
}
-
+
/**
* @param columns
* @param rows
@@ -51,7 +51,7 @@ public class SelectionArea {
maxColumns = columns - 1;
maxRows = rows - 1;
}
-
+
private int checkBounds(int value, int max) {
if (value < 0)
return 0;
@@ -60,115 +60,115 @@ public class SelectionArea {
else
return value;
}
-
+
public boolean isSelectingOrigin() {
return selectingOrigin;
}
-
+
public void finishSelectingOrigin() {
selectingOrigin = false;
}
-
+
public void setTop(int top) {
this.top = bottom = checkBounds(top, maxRows);
}
-
+
public void decrementTop() {
setTop(--top);
}
-
+
public void incrementTop() {
setTop(++top);
}
-
+
public int getTop() {
return Math.min(top, bottom);
}
-
+
public void setBottom(int bottom) {
this.bottom = checkBounds(bottom, maxRows);
}
-
+
public void decrementBottom() {
setBottom(--bottom);
}
-
+
public void incrementBottom() {
setBottom(++bottom);
}
-
+
public int getBottom() {
return Math.max(top, bottom);
}
-
+
public void setLeft(int left) {
this.left = right = checkBounds(left, maxColumns);
}
-
+
public void decrementLeft() {
setLeft(--left);
}
-
+
public void incrementLeft() {
setLeft(++left);
}
-
+
public int getLeft() {
return Math.min(left, right);
}
-
+
public void setRight(int right) {
this.right = checkBounds(right, maxColumns);
}
-
+
public void decrementRight() {
setRight(--right);
}
-
+
public void incrementRight() {
setRight(++right);
}
-
+
public int getRight() {
return Math.max(left, right);
}
-
+
public String copyFrom(VDUBuffer vb) {
int size = (getRight() - getLeft() + 1) * (getBottom() - getTop() + 1);
-
+
StringBuffer buffer = new StringBuffer(size);
-
+
for(int y = getTop(); y <= getBottom(); y++) {
int lastNonSpace = buffer.length();
-
+
for (int x = getLeft(); x <= getRight(); x++) {
// only copy printable chars
char c = vb.getChar(x, y);
-
+
if (!Character.isDefined(c) ||
(Character.isISOControl(c) && c != '\t'))
c = ' ';
-
+
if (c != ' ')
lastNonSpace = buffer.length();
-
+
buffer.append(c);
}
-
+
// Don't leave a bunch of spaces in our copy buffer.
if (buffer.length() > lastNonSpace)
buffer.delete(lastNonSpace + 1, buffer.length());
-
+
if (y != bottom)
buffer.append("\n");
}
-
+
return buffer.toString();
}
-
+
public String toString() {
StringBuilder buffer = new StringBuilder();
-
+
buffer.append("SelectionArea[top=");
buffer.append(top);
buffer.append(", bottom=");
@@ -184,7 +184,7 @@ public class SelectionArea {
buffer.append(", isSelectingOrigin=");
buffer.append(isSelectingOrigin());
buffer.append("]");
-
+
return buffer.toString();
}
}
diff --git a/src/org/connectbot/service/BridgeDisconnectedListener.java b/src/org/connectbot/service/BridgeDisconnectedListener.java
index 74ab0f2..70c394e 100644
--- a/src/org/connectbot/service/BridgeDisconnectedListener.java
+++ b/src/org/connectbot/service/BridgeDisconnectedListener.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
diff --git a/src/org/connectbot/service/PromptHelper.java b/src/org/connectbot/service/PromptHelper.java
index 2fc5183..1523324 100644
--- a/src/org/connectbot/service/PromptHelper.java
+++ b/src/org/connectbot/service/PromptHelper.java
@@ -8,32 +8,32 @@ import android.os.Message;
/**
* Helps provide a relay for prompts and responses between a possible user
* interface and some underlying service.
- *
+ *
* @author jsharkey
*/
public class PromptHelper {
private final Object tag;
private Handler handler = null;
-
+
private Semaphore promptToken;
private Semaphore promptResponse;
-
+
public String promptHint = null;
public Object promptRequested = null;
-
+
private Object response = null;
-
+
public PromptHelper(Object tag) {
this.tag = tag;
-
+
// Threads must acquire this before they can send a prompt.
promptToken = new Semaphore(1);
-
+
// Responses will release this semaphore.
promptResponse = new Semaphore(0);
}
-
+
/**
* Register a user interface handler, if available.
@@ -50,7 +50,7 @@ public class PromptHelper {
response = value;
promptResponse.release();
}
-
+
/**
* Return the internal response value just before erasing and returning it.
*/
@@ -69,32 +69,32 @@ public class PromptHelper {
*/
private Object requestPrompt(String hint, Object type, boolean immediate) throws InterruptedException {
Object response = null;
-
+
if (immediate)
cancelPrompt();
-
+
promptToken.acquire();
try {
promptHint = hint;
promptRequested = type;
-
+
// notify any parent watching for live events
if (handler != null)
Message.obtain(handler, -1, tag).sendToTarget();
-
+
// acquire lock until user passes back value
promptResponse.acquire();
promptRequested = null;
-
+
response = popResponse();
} finally {
promptToken.release();
}
-
+
return response;
}
-
+
/**
* Request a string response from parent. This is a blocking call until user
* interface returns a value.
@@ -110,7 +110,7 @@ public class PromptHelper {
}
return value;
}
-
+
/**
* Convenience method for requestStringPrompt(String, boolean)
* @param hint prompt hint for user to answer
@@ -119,7 +119,7 @@ public class PromptHelper {
public String requestStringPrompt(String hint) {
return requestStringPrompt(hint, false);
}
-
+
/**
* Request a boolean response from parent. This is a blocking call until user
* interface returns a value.
@@ -135,7 +135,7 @@ public class PromptHelper {
}
return value;
}
-
+
/**
* Convenience method for requestBooleanPrompt(String, boolean)
* @param hint String to present to user in prompt
@@ -144,7 +144,7 @@ public class PromptHelper {
public Boolean requestBooleanPrompt(String hint) {
return requestBooleanPrompt(hint, false);
}
-
+
/**
* Cancel an in-progress prompt.
*/
diff --git a/src/org/connectbot/service/TerminalBridge.java b/src/org/connectbot/service/TerminalBridge.java
index 2522caa..5e7c2dc 100644
--- a/src/org/connectbot/service/TerminalBridge.java
+++ b/src/org/connectbot/service/TerminalBridge.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -82,53 +82,53 @@ import de.mud.terminal.vt320;
* This separation allows us to keep the TerminalBridge running in a background
* service. A TerminalView shares down a bitmap that we can use for rendering
* when available.
- *
+ *
* This class also provides SSH hostkey verification prompting, and password
* prompting.
*/
public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCallback, ConnectionMonitor {
-
+
public final static String TAG = TerminalBridge.class.toString();
-
+
private final static int BUFFER_SIZE = 4096;
public final static int DEFAULT_FONT_SIZE = 10;
-
+
public static final String AUTH_PUBLICKEY = "publickey",
AUTH_PASSWORD = "password",
AUTH_KEYBOARDINTERACTIVE = "keyboard-interactive";
-
+
protected final static int AUTH_TRIES = 20;
private List<PortForwardBean> portForwards = new LinkedList<PortForwardBean>();
-
+
public int color[];
-
+
public final static int COLOR_FG_STD = 7;
public final static int COLOR_BG_STD = 0;
-
+
protected final TerminalManager manager;
public HostBean host;
-
+
public final Connection connection;
protected Session session;
-
+
private final Paint defaultPaint;
protected OutputStream stdin;
protected InputStream stdout;
-
+
private InputStream stderr;
private Thread relay;
-
+
private final String emulation;
private final int scrollback;
public Bitmap bitmap = null;
public VDUBuffer buffer = null;
-
+
private TerminalView parent = null;
private Canvas canvas = new Canvas();
@@ -139,7 +139,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
private boolean tabKeyPressed = false;
private boolean pubkeysExhausted = false;
-
+
private boolean authenticated = false;
private boolean sessionOpen = false;
private boolean disconnected = false;
@@ -148,9 +148,9 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
private boolean forcedSize = false;
private int termWidth;
private int termHeight;
-
+
private String keymode = null;
-
+
private boolean selectingForCopy = false;
private SelectionArea selectionArea;
private ClipboardManager clipboard;
@@ -162,9 +162,9 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
private int charDescent = -1;
private float fontSize = -1;
-
+
private List<String> localOutput;
-
+
/**
* Flag indicating if we should perform a full-screen redraw during our next
* rendering pass.
@@ -178,17 +178,17 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
protected ConnectionInfo connectionInfo;
public class HostKeyVerifier implements ServerHostKeyVerifier {
-
+
public boolean verifyServerHostKey(String hostname, int port, String serverHostKeyAlgorithm, byte[] serverHostKey) throws Exception {
// read in all known hosts from hostdb
KnownHosts hosts = manager.hostdb.getKnownHosts();
Boolean result;
-
+
String matchName = String.format("%s:%d", hostname, port);
-
+
String fingerprint = KnownHosts.createHexFingerprint(serverHostKeyAlgorithm, serverHostKey);
-
+
String algorithmName;
if ("ssh-rsa".equals(serverHostKeyAlgorithm))
algorithmName = "RSA";
@@ -196,7 +196,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
algorithmName = "DSA";
else
algorithmName = serverHostKeyAlgorithm;
-
+
switch(hosts.verifyHostkey(matchName, serverHostKeyAlgorithm, serverHostKey)) {
case KnownHosts.HOSTKEY_IS_OK:
outputLine(String.format("Verified host %s key: %s", algorithmName, fingerprint));
@@ -214,7 +214,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
manager.hostdb.saveKnownHost(hostname, port, serverHostKeyAlgorithm, serverHostKey);
}
return result.booleanValue();
-
+
case KnownHosts.HOSTKEY_HAS_CHANGED:
outputLine("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
outputLine("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @");
@@ -224,7 +224,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
outputLine("It is also possible that the host key has just been changed.");
outputLine(String.format("Host %s key fingerprint is %s",
algorithmName, fingerprint));
-
+
// Users have no way to delete keys, so we'll prompt them for now.
result = promptHelper.requestBooleanPrompt("Are you sure you want\nto continue connecting?");
if(result == null) return false;
@@ -232,41 +232,41 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
// save this key in known database
manager.hostdb.saveKnownHost(hostname, port, serverHostKeyAlgorithm, serverHostKey);
}
- return result.booleanValue();
+ return result.booleanValue();
}
-
+
return false;
-
+
}
-
+
}
-
+
/**
* Create new terminal bridge with following parameters. We will immediately
* launch thread to start SSH connection and handle any hostkey verification
* and password authentication.
*/
public TerminalBridge(final TerminalManager manager, final HostBean host) throws Exception {
-
+
this.manager = manager;
this.host = host;
-
+
emulation = manager.getEmulation();
scrollback = manager.getScrollback();
// create prompt helper to relay password and hostkey requests up to gui
promptHelper = new PromptHelper(this);
-
+
// create our default paint
defaultPaint = new Paint();
defaultPaint.setAntiAlias(true);
defaultPaint.setTypeface(Typeface.MONOSPACE);
defaultPaint.setFakeBoldText(true); // more readable?
-
+
localOutput = new LinkedList<String>();
-
+
setFontSize(DEFAULT_FONT_SIZE);
-
+
// create terminal buffer and handle outgoing data
// this is probably status reply information
buffer = new vt320() {
@@ -291,12 +291,12 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
buffer.setBufferSize(scrollback);
resetColors();
buffer.setDisplay(this);
-
+
selectionArea = new SelectionArea();
// TODO Change this when hosts are beans as well
portForwards = manager.hostdb.getPortForwardsForHost(host);
-
+
// prepare the ssh connection for opening
// we perform the actual connection later in startConnection()
outputLine(String.format("Connecting to %s:%d", host.getHostname(), host.getPort()));
@@ -304,7 +304,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
connection.addConnectionMonitor(this);
connection.setCompression(host.getCompression());
}
-
+
/**
* Spawn thread to open connection and start login process.
*/
@@ -313,7 +313,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
public void run() {
try {
connectionInfo = connection.connect(new HostKeyVerifier());
-
+
if (connectionInfo.clientToServerCryptoAlgorithm
.equals(connectionInfo.serverToClientCryptoAlgorithm)
&& connectionInfo.clientToServerMACAlgorithm
@@ -334,30 +334,30 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
}
} catch (IOException e) {
Log.e(TAG, "Problem in SSH connection thread during authentication", e);
-
+
// Display the reason in the text.
outputLine(e.getCause().getMessage());
dispatchDisconnect(false);
return;
}
-
- try {
+
+ try {
// enter a loop to keep trying until authentication
int tries = 0;
while(!connection.isAuthenticationComplete() && tries++ < AUTH_TRIES && !disconnected) {
handleAuthentication();
-
+
// sleep to make sure we dont kill system
Thread.sleep(1000);
}
} catch(Exception e) {
Log.e(TAG, "Problem in SSH connection thread during authentication", e);
}
- }
+ }
}).start();
}
-
+
/**
* Attempt connection with database row pointed to by cursor.
* @param cursor
@@ -372,21 +372,21 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
// load this key from memory if its already there
Log.d(TAG, String.format("Found unlocked key '%s' already in-memory", pubkey.getNickname()));
trileadKey = manager.getKey(pubkey.getNickname());
-
+
} else {
// otherwise load key from database and prompt for password as needed
String password = null;
if (pubkey.isEncrypted()) {
password = promptHelper.requestStringPrompt(String.format("Password for key '%s'", pubkey.getNickname()));
-
+
// Something must have interrupted the prompt.
if (password == null)
return false;
}
-
+
if(PubkeyDatabase.KEY_TYPE_IMPORTED.equals(pubkey.getType())) {
// load specific key using pem format
- trileadKey = PEMDecoder.decode(new String(pubkey.getPrivateKey()).toCharArray(), password);
+ trileadKey = PEMDecoder.decode(new String(pubkey.getPrivateKey()).toCharArray(), password);
} else {
// load using internal generated format
PrivateKey privKey;
@@ -399,10 +399,10 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
outputLine(message);
return false;
}
-
+
PublicKey pubKey = PubkeyUtils.decodePublic(pubkey.getPublicKey(),
pubkey.getType());
-
+
// convert key to trilead format
trileadKey = PubkeyUtils.convertToTrilead(privKey, pubKey);
Log.d(TAG, "Unlocked key " + PubkeyUtils.formatKey(pubKey));
@@ -417,9 +417,9 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
}
return this.tryPublicKey(host.getUsername(), pubkey.getNickname(), trileadKey);
-
+
}
-
+
private boolean tryPublicKey(String username, String keyNickname, Object trileadKey) throws IOException {
//outputLine(String.format("Attempting 'publickey' with key '%s' [%s]...", keyNickname, trileadKey.toString()));
boolean success = connection.authenticateWithPublicKey(username, trileadKey);
@@ -427,7 +427,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
outputLine(String.format("Authentication method 'publickey' with key '%s' failed", keyNickname));
return success;
}
-
+
protected void handleAuthentication() {
try {
if (connection.authenticateWithNone(host.getUsername())) {
@@ -437,19 +437,19 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
} catch(Exception e) {
Log.d(TAG, "Host does not support 'none' authentication.");
}
-
+
outputLine("Trying to authenticate");
-
+
try {
long pubkeyId = host.getPubkeyId();
-
+
if (!pubkeysExhausted &&
pubkeyId != HostDatabase.PUBKEYID_NEVER &&
connection.isAuthMethodAvailable(host.getUsername(), AUTH_PUBLICKEY)) {
-
+
// if explicit pubkey defined for this host, then prompt for password as needed
// otherwise just try all in-memory keys held in terminalmanager
-
+
if (pubkeyId == HostDatabase.PUBKEYID_ANY) {
// try each of the in-memory keys
outputLine("Attempting 'publickey' authentication with any in-memory SSH keys");
@@ -464,14 +464,14 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
outputLine("Attempting 'publickey' authentication with a specific public key");
// use a specific key for this host, as requested
PubkeyBean pubkey = manager.pubkeydb.findPubkeyById(pubkeyId);
-
+
if (pubkey == null)
outputLine("Selected public key is invalid, try reselecting key in host editor");
else
if (tryPublicKey(pubkey))
finishConnection();
}
-
+
pubkeysExhausted = true;
} else if (connection.isAuthMethodAvailable(host.getUsername(), AUTH_PASSWORD)) {
outputLine("Attempting 'password' authentication");
@@ -482,27 +482,27 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
} else {
outputLine("Authentication method 'password' failed");
}
-
+
} else if(connection.isAuthMethodAvailable(host.getUsername(), AUTH_KEYBOARDINTERACTIVE)) {
// this auth method will talk with us using InteractiveCallback interface
- // it blocks until authentication finishes
+ // it blocks until authentication finishes
outputLine("Attempting 'keyboard-interactive' authentication");
if(connection.authenticateWithKeyboardInteractive(host.getUsername(), TerminalBridge.this)) {
finishConnection();
} else {
outputLine("Authentication method 'keyboard-interactive' failed");
}
-
+
} else {
outputLine("[Your host doesn't support 'password' or 'keyboard-interactive' authentication.]");
-
- }
+
+ }
} catch(Exception e) {
Log.e(TAG, "Problem during handleAuthentication()", e);
}
-
+
}
-
+
/**
* Handle challenges from keyboard-interactive authentication mode.
*/
@@ -515,7 +515,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
return responses;
}
-
+
/**
* Convenience method for writing a line into the underlying MUD buffer.
* Should never be called once the session is established.
@@ -523,12 +523,12 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
protected void outputLine(String line) {
if (session != null)
Log.e(TAG, "Session established, cannot use outputLine!", new IOException("outputLine call traceback"));
-
+
synchronized (localOutput) {
final String s = line + "\r\n";
-
+
localOutput.add(s);
-
+
((vt320) buffer).putString(s);
}
}
@@ -549,14 +549,14 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
}
}).start();
}
-
+
/**
* Internal method to request actual PTY terminal once we've finished
* authentication. If called before authenticated, it will just fail.
*/
private void finishConnection() {
setAuthenticated(true);
-
+
// Start up predefined port forwards
for (PortForwardBean pfb : portForwards) {
try {
@@ -566,16 +566,16 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
Log.e(TAG, "Error setting up port forward during connect", e);
}
}
-
+
if (!host.getWantSession()) {
outputLine("Session will not be started due to host preference.");
return;
}
-
+
try {
session = connection.openSession();
((vt320) buffer).reset();
-
+
// We no longer need our local output.
localOutput.clear();
@@ -585,7 +585,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
((vt320) buffer).setAnswerBack(emulation);
session.requestPTY(emulation, termWidth, termHeight, 0, 0, null);
session.startShell();
-
+
// grab stdin/out from newly formed session
stdin = session.getStdin();
stdout = session.getStdout();
@@ -595,74 +595,74 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
relay = new Thread(new Runnable() {
public void run() {
final String encoding = host.getEncoding();
-
+
byte[] b = new byte[BUFFER_SIZE];
-
+
Charset charset = Charset.forName(encoding);
-
+
/* Set up character set decoder to report any byte sequences
* which are malformed so we can try to resume decoding it
* on the next packet received.
- *
+ *
* UTF-8 byte sequences have a tendency to get truncated at
* times.
*/
CharsetDecoder cd = charset.newDecoder();
cd.onUnmappableCharacter(CodingErrorAction.REPLACE);
cd.onMalformedInput(CodingErrorAction.REPORT);
-
+
CharsetDecoder replacer = charset.newDecoder();
replacer.onUnmappableCharacter(CodingErrorAction.REPLACE);
replacer.onMalformedInput(CodingErrorAction.REPLACE);
-
+
ByteBuffer bb;
CharBuffer cb = CharBuffer.allocate(BUFFER_SIZE);
-
+
int n = 0;
int offset = 0;
-
+
int conditions = ChannelCondition.STDOUT_DATA
| ChannelCondition.STDERR_DATA
| ChannelCondition.CLOSED
| ChannelCondition.EOF;
int newConditions = 0;
-
+
while((newConditions & ChannelCondition.CLOSED) == 0) {
try {
newConditions = session.waitForCondition(conditions, 0);
if ((newConditions & ChannelCondition.STDOUT_DATA) != 0) {
while (stdout.available() > 0) {
n = offset + stdout.read(b, offset, BUFFER_SIZE - offset);
-
+
bb = ByteBuffer.wrap(b, 0, n);
- CoderResult cr = cd.decode(bb, cb, true);
-
+ CoderResult cr = cd.decode(bb, cb, true);
+
if (cr.isMalformed()) {
int curpos = bb.position() - cr.length();
-
+
if (curpos > 0) {
/* There is good data before the malformed section, so
* pass this on immediately.
*/
((vt320)buffer).putString(cb.array(), 0, cb.position());
}
-
+
while (bb.position() < n) {
bb = ByteBuffer.wrap(b, curpos, cr.length());
-
+
cb.clear();
replacer.decode(bb, cb, true);
-
+
((vt320) buffer).putString(cb.array(), 0, cb.position());
-
+
curpos += cr.length();
-
+
bb = ByteBuffer.wrap(b, curpos, n - curpos);
-
+
cb.clear();
cr = cd.decode(bb, cb, true);
}
-
+
if (cr.isMalformed()) {
/* If we still have malformed input, save the bytes for the next
* read and try to parse it again.
@@ -689,12 +689,12 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
((vt320)buffer).putString(cb.array(), 0, cb.position());
offset = 0;
}
-
+
cb.clear();
}
redraw();
}
-
+
if ((newConditions & ChannelCondition.STDERR_DATA) != 0) {
while (stderr.available() > 0) {
n = stderr.read(b);
@@ -705,7 +705,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
cb.clear();
}
}
-
+
if ((newConditions & ChannelCondition.EOF) != 0) {
// The other side closed our channel, so let's disconnect.
// TODO review whether any tunnel is in use currently.
@@ -723,16 +723,16 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
// force font-size to make sure we resizePTY as needed
setFontSize(fontSize);
-
+
sessionOpen = true;
-
+
// finally send any post-login string, if requested
injectString(host.getPostLogin());
} catch (IOException e1) {
Log.e(TAG, "Problem while trying to create PTY in finishConnection()", e1);
}
-
+
}
/**
@@ -745,7 +745,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
public void setOnDisconnectedListener(BridgeDisconnectedListener disconnectListener) {
this.disconnectListener = disconnectListener;
}
-
+
/**
* Force disconnection of this terminal bridge.
*/
@@ -753,7 +753,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
// We don't need to do this multiple times.
if (disconnected && !immediate)
return;
-
+
// disconnection request hangs if we havent really connected to a host yet
// temporary fix is to just spawn disconnection into a thread
new Thread(new Runnable() {
@@ -763,11 +763,11 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
connection.close();
}
}).start();
-
+
disconnected = true;
authenticated = false;
sessionOpen = false;
-
+
if (immediate) {
awaitingClose = true;
if (disconnectListener != null)
@@ -778,7 +778,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
Boolean result = promptHelper.requestBooleanPrompt("Host has disconnected.\nClose session?", true);
if (result == null || result.booleanValue()) {
awaitingClose = true;
-
+
// Tell the TerminalManager that we can be destroyed now.
if (disconnectListener != null)
disconnectListener.onDisconnected(TerminalBridge.this);
@@ -787,7 +787,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
}).start();
}
}
-
+
public void refreshKeymode() {
keymode = manager.getKeyMode();
}
@@ -796,7 +796,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
public Vibrator vibrator = null;
public static final long VIBRATE_DURATION = 30;
-
+
/**
* Handle onKey() events coming down from a {@link TerminalView} above us.
* We might collect these for our internal buffer when working with hostkeys
@@ -810,7 +810,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
// skip keys if we aren't connected yet or have been disconnected
if (disconnected || session == null)
return false;
-
+
if ("Use right-side keys".equals(keymode)) {
if (keyCode == KeyEvent.KEYCODE_ALT_RIGHT && slashKeyPressed) {
stdin.write('/');
@@ -828,7 +828,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
return true;
}
}
-
+
return false;
}
@@ -843,48 +843,48 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
setFontSize(fontSize - 2);
return true;
}
-
+
// skip keys if we aren't connected yet or have been disconnected
if (disconnected || session == null)
return false;
-
+
// if we're in scrollback, scroll to bottom of window on input
- if (buffer.windowBase != buffer.screenBase)
+ if (buffer.windowBase != buffer.screenBase)
buffer.setWindowBase(buffer.screenBase);
-
+
boolean printing = (keymap.isPrintingKey(keyCode) || keyCode == KeyEvent.KEYCODE_SPACE);
-
+
// otherwise pass through to existing session
// print normal keys
if (printing) {
int metaState = event.getMetaState();
-
+
slashKeyPressed = tabKeyPressed = false;
-
+
if (shiftPressed) {
metaState |= KeyEvent.META_SHIFT_ON;
shiftPressed = false;
}
-
+
if (altPressed) {
metaState |= KeyEvent.META_ALT_ON;
altPressed = false;
}
-
+
int key = keymap.get(keyCode, metaState);
-
+
if (ctrlPressed) {
- // Support CTRL-a through CTRL-z
- if (key >= 0x61 && key <= 0x7A)
- key -= 0x60;
- // Support CTRL-A through CTRL-_
- else if (key >= 0x41 && key <= 0x5F)
- key -= 0x40;
- else if (key == 0x20)
- key = 0x00;
- ctrlPressed = false;
+ // Support CTRL-a through CTRL-z
+ if (key >= 0x61 && key <= 0x7A)
+ key -= 0x60;
+ // Support CTRL-A through CTRL-_
+ else if (key >= 0x41 && key <= 0x5F)
+ key -= 0x40;
+ else if (key == 0x20)
+ key = 0x00;
+ ctrlPressed = false;
}
-
+
// handle pressing f-keys
if((event.getMetaState() & KeyEvent.META_SHIFT_ON) != 0) {
//Log.d(TAG, "yay pressing an fkey");
@@ -901,11 +901,11 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
case ')': ((vt320)buffer).keyPressed(vt320.KEY_F10, ' ', 0); return true;
}
}
-
+
stdin.write(key);
return true;
}
-
+
// try handling keymode shortcuts
if("Use right-side keys".equals(keymode)) {
switch(keyCode) {
@@ -926,25 +926,25 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
// look for special chars
switch(keyCode) {
case KeyEvent.KEYCODE_CAMERA:
-
+
// check to see which shortcut the camera button triggers
String camera = manager.prefs.getString(manager.res.getString(R.string.pref_camera), manager.res.getString(R.string.list_camera_ctrlaspace));
if(manager.res.getString(R.string.list_camera_ctrlaspace).equals(camera)) {
stdin.write(0x01);
stdin.write(' ');
-
+
} else if(manager.res.getString(R.string.list_camera_ctrla).equals(camera)) {
stdin.write(0x01);
-
+
} else if(manager.res.getString(R.string.list_camera_esc).equals(camera)) {
((vt320)buffer).keyTyped(vt320.KEY_ESCAPE, ' ', 0);
-
+
}
//((vt320)buffer).keyTyped('a', 'a', vt320.KEY_CONTROL);
//((vt320)buffer).keyTyped(' ', ' ', 0);
break;
-
+
case KeyEvent.KEYCODE_DEL: stdin.write(0x08); return true;
case KeyEvent.KEYCODE_ENTER: ((vt320)buffer).keyTyped(vt320.KEY_ENTER, ' ', event.getMetaState()); return true;
case KeyEvent.KEYCODE_DPAD_LEFT:
@@ -1007,16 +1007,16 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
if (parent != null && clipboard != null) {
// copy selected area to clipboard
String copiedText = selectionArea.copyFrom(buffer);
-
+
clipboard.setText(copiedText);
parent.notifyUser(parent.getContext().getString(R.string.console_copy_done,
copiedText.length()));
-
+
selectingForCopy = false;
selectionArea.reset();
}
}
-
+
redraw();
} else {
// TODO: Add some visual indication of Ctrl state
@@ -1028,7 +1028,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
}
return true;
}
-
+
} catch (IOException e) {
Log.e(TAG, "Problem while trying to handle an onKey() event", e);
try {
@@ -1042,22 +1042,22 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
Log.d(TAG, "Input before connection established ignored.");
return true;
}
-
+
return false;
}
-
+
public void setSelectingForCopy(boolean selectingForCopy) {
this.selectingForCopy = selectingForCopy;
}
-
+
public boolean isSelectingForCopy() {
return selectingForCopy;
}
-
+
public SelectionArea getSelectionArea() {
return selectionArea;
}
-
+
public synchronized void tryKeyVibrate() {
if (bumpyArrows && vibrator != null)
vibrator.vibrate(VIBRATE_DURATION);
@@ -1070,24 +1070,24 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
private void setFontSize(float size) {
if (size <= 0.0)
return;
-
+
defaultPaint.setTextSize(size);
fontSize = size;
-
+
// read new metrics to get exact pixel dimensions
FontMetricsInt fm = defaultPaint.getFontMetricsInt();
charDescent = fm.descent;
-
+
float[] widths = new float[1];
defaultPaint.getTextWidths("X", widths);
charWidth = (int)widths[0];
charHeight = Math.abs(fm.top) + Math.abs(fm.descent) + 1;
-
+
// refresh any bitmap with new font size
if(parent != null)
parentChanged(parent);
}
-
+
/**
* Something changed in our parent {@link TerminalView}, maybe it's a new
* parent, or maybe it's an updated font size. We should recalculate
@@ -1097,37 +1097,37 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
this.parent = parent;
int width = parent.getWidth();
int height = parent.getHeight();
-
+
bumpyArrows = manager.prefs.getBoolean(manager.res.getString(R.string.pref_bumpyarrows), true);
vibrator = (Vibrator) parent.getContext().getSystemService(Context.VIBRATOR_SERVICE);
clipboard = (ClipboardManager) parent.getContext().getSystemService(Context.CLIPBOARD_SERVICE);
-
+
if (!forcedSize) {
// recalculate buffer size
int newTermWidth, newTermHeight;
newTermWidth = width / charWidth;
newTermHeight = height / charHeight;
-
+
// If nothing has changed in the terminal dimensions and not an intial
// draw then don't blow away scroll regions and such.
if (newTermWidth == termWidth && newTermHeight == termHeight)
return;
-
+
termWidth = newTermWidth;
termHeight = newTermHeight;
}
-
+
// reallocate new bitmap if needed
boolean newBitmap = (bitmap == null);
if(bitmap != null)
newBitmap = (bitmap.getWidth() != width || bitmap.getHeight() != height);
-
+
if(newBitmap) {
bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
canvas.setBitmap(bitmap);
}
-
+
// clear out any old buffer information
defaultPaint.setColor(Color.BLACK);
canvas.drawRect(0, 0, width, height, defaultPaint);
@@ -1136,7 +1136,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
if (forcedSize) {
int borderX = (termWidth * charWidth) + 1;
int borderY = (termHeight * charHeight) + 1;
-
+
defaultPaint.setColor(Color.GRAY);
defaultPaint.setStrokeWidth(0.0f);
if (width >= borderX)
@@ -1144,40 +1144,40 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
if (height >= borderY)
canvas.drawLine(0, borderY, borderX + 1, borderY, defaultPaint);
}
-
+
try {
// request a terminal pty resize
int prevRow = buffer.getCursorRow();
buffer.setScreenSize(termWidth, termHeight, true);
-
+
// Work around weird vt320.java behavior where cursor is an offset from the bottom??
buffer.setCursorPosition(buffer.getCursorColumn(), prevRow);
-
+
if(session != null)
session.resizePTY(termWidth, termHeight);
} catch(Exception e) {
Log.e(TAG, "Problem while trying to resize screen or PTY", e);
}
-
+
// redraw local output if we don't have a sesson to receive our resize request
if (session == null) {
synchronized (localOutput) {
((vt320) buffer).reset();
-
+
for (String line : localOutput)
((vt320) buffer).putString(line);
}
}
-
+
// force full redraw with new buffer size
fullRedraw = true;
redraw();
this.parent.notifyUser(String.format("%d x %d", termWidth, termHeight));
-
+
Log.i(TAG, String.format("parentChanged() now width=%d, height=%d", termWidth, termHeight));
}
-
+
/**
* Somehow our parent {@link TerminalView} was destroyed. Now we don't need
* to redraw anywhere, and we can recycle our internal bitmap.
@@ -1197,21 +1197,21 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
public VDUBuffer getVDUBuffer() {
return buffer;
}
-
+
public void onDraw() {
int fg, bg;
boolean entireDirty = buffer.update[0] || fullRedraw;
-
+
// walk through all lines in the buffer
for(int l = 0; l < buffer.height; l++) {
-
+
// check if this line is dirty and needs to be repainted
// also check for entire-buffer dirty flags
if (!entireDirty && !buffer.update[l + 1]) continue;
-
+
// reset dirty flag for this line
buffer.update[l + 1] = false;
-
+
// walk through all characters in this line
for (int c = 0; c < buffer.width; c++) {
int addr = 0;
@@ -1220,7 +1220,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
// reset default colors
fg = color[COLOR_FG_STD];
bg = color[COLOR_BG_STD];
-
+
// check if foreground color attribute is set
if ((currAttr & VDUBuffer.COLOR_FG) != 0) {
int fgcolor = ((currAttr & VDUBuffer.COLOR_FG) >> VDUBuffer.COLOR_FG_SHIFT) - 1;
@@ -1233,38 +1233,38 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
// check if background color attribute is set
if ((currAttr & VDUBuffer.COLOR_BG) != 0)
bg = color[((currAttr & VDUBuffer.COLOR_BG) >> VDUBuffer.COLOR_BG_SHIFT) - 1];
-
+
// support character inversion by swapping background and foreground color
if ((currAttr & VDUBuffer.INVERT) != 0) {
int swapc = bg;
bg = fg;
fg = swapc;
}
-
+
// set underlined attributes if requested
defaultPaint.setUnderlineText((currAttr & VDUBuffer.UNDERLINE) != 0);
-
+
// determine the amount of continuous characters with the same settings and print them all at once
while(c + addr < buffer.width && buffer.charAttributes[buffer.windowBase + l][c + addr] == currAttr) {
addr++;
}
-
+
// clear this dirty area with background color
defaultPaint.setColor(bg);
canvas.drawRect(c * charWidth, (l * charHeight) - 1, (c + addr) * charWidth, (l + 1) * charHeight, defaultPaint);
-
+
// write the text string starting at 'c' for 'addr' number of characters
defaultPaint.setColor(fg);
if((currAttr & VDUBuffer.INVISIBLE) == 0)
canvas.drawText(buffer.charArray[buffer.windowBase + l], c,
addr, c * charWidth, ((l + 1) * charHeight) - charDescent - 2,
defaultPaint);
-
+
// advance to the next text block with different characteristics
c += addr - 1;
}
}
-
+
// reset entire-buffer flags
buffer.update[0] = false;
fullRedraw = false;
@@ -1274,7 +1274,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
if (parent != null)
parent.postInvalidate();
}
-
+
public void updateScrollBar() {
}
@@ -1295,20 +1295,20 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
float size = 8.0f;
float step = 8.0f;
float limit = 0.125f;
-
+
int direction;
while ((direction = fontSizeCompare(size, cols, rows, width, height)) < 0)
size += step;
-
+
if (direction == 0) {
Log.d("fontsize", String.format("Found match at %f", size));
return;
}
-
+
step /= 2.0f;
size -= step;
-
+
while ((direction = fontSizeCompare(size, cols, rows, width, height)) != 0
&& step >= limit) {
step /= 2.0f;
@@ -1318,35 +1318,35 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
size += step;
}
}
-
+
if (direction > 0)
size -= step;
-
+
forcedSize = true;
termWidth = cols;
termHeight = rows;
setFontSize(size);
}
-
+
private int fontSizeCompare(float size, int cols, int rows, int width, int height) {
// read new metrics to get exact pixel dimensions
defaultPaint.setTextSize(size);
FontMetricsInt fm = defaultPaint.getFontMetricsInt();
-
+
float[] widths = new float[1];
defaultPaint.getTextWidths("X", widths);
int termWidth = (int)widths[0] * cols;
int termHeight = (Math.abs(fm.top) + Math.abs(fm.descent) + 1) * rows;
-
+
Log.d("fontsize", String.format("font size %f resulted in %d x %d", size, termWidth, termHeight));
-
+
// Check to see if it fits in resolution specified.
if (termWidth > width || termHeight > height)
return 1;
-
+
if (termWidth == width || termHeight == height)
return 0;
-
+
return -1;
}
@@ -1367,10 +1367,10 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
public boolean removePortForward(PortForwardBean portForward) {
// Make sure we don't have a phantom forwarder.
disablePortForward(portForward);
-
+
return portForwards.remove(portForward);
}
-
+
/**
* @return the list of port forwards
*/
@@ -1389,7 +1389,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
Log.e(TAG, "Attempt to enable port forward not in list");
return false;
}
-
+
if (HostDatabase.PORTFORWARD_LOCAL.equals(portForward.getType())) {
LocalPortForwarder lpf = null;
try {
@@ -1398,12 +1398,12 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
Log.e(TAG, "Could not create local port forward", e);
return false;
}
-
+
if (lpf == null) {
Log.e(TAG, "returned LocalPortForwarder object is null");
return false;
}
-
+
portForward.setIdentifier(lpf);
portForward.setEnabled(true);
return true;
@@ -1414,19 +1414,19 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
Log.e(TAG, "Could not create remote port forward", e);
return false;
}
-
+
portForward.setEnabled(false);
return true;
} else if (HostDatabase.PORTFORWARD_DYNAMIC5.equals(portForward.getType())) {
DynamicPortForwarder dpf = null;
-
+
try {
dpf = connection.createDynamicPortForwarder(portForward.getSourcePort());
} catch (IOException e) {
Log.e(TAG, "Could not create dynamic port forward", e);
return false;
}
-
+
portForward.setIdentifier(dpf);
portForward.setEnabled(true);
return true;
@@ -1448,16 +1448,16 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
Log.e(TAG, "Attempt to disable port forward not in list");
return false;
}
-
+
if (HostDatabase.PORTFORWARD_LOCAL.equals(portForward.getType())) {
LocalPortForwarder lpf = null;
lpf = (LocalPortForwarder)portForward.getIdentifier();
-
+
if (!portForward.isEnabled() || lpf == null) {
Log.d(TAG, String.format("Could not disable %s; it appears to be not enabled or have no handler", portForward.getNickname()));
return false;
}
-
+
portForward.setEnabled(false);
try {
@@ -1466,7 +1466,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
Log.e(TAG, "Could not stop local port forwarder, setting enabled to false", e);
return false;
}
-
+
return true;
} else if (HostDatabase.PORTFORWARD_REMOTE.equals(portForward.getType())) {
portForward.setEnabled(false);
@@ -1477,26 +1477,26 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
Log.e(TAG, "Could not stop remote port forwarding, setting enabled to false", e);
return false;
}
-
+
return true;
} else if (HostDatabase.PORTFORWARD_DYNAMIC5.equals(portForward.getType())) {
DynamicPortForwarder dpf = null;
dpf = (DynamicPortForwarder)portForward.getIdentifier();
-
+
if (!portForward.isEnabled() || dpf == null) {
Log.d(TAG, String.format("Could not disable %s; it appears to be not enabled or have no handler", portForward.getNickname()));
return false;
}
-
+
portForward.setEnabled(false);
-
+
try {
dpf.close();
} catch (IOException e) {
Log.e(TAG, "Could not stop dynamic port forwarder, setting enabled to false", e);
return false;
}
-
+
return true;
} else {
// Unsupported type
@@ -1525,7 +1525,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
public boolean isAwaitingClose() {
return awaitingClose;
}
-
+
/**
* @return whether this connection had started and subsequently disconnected
*/
@@ -1541,7 +1541,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
if (index < color.length && index >= 16)
color[index] = 0xff000000 | red << 16 | green << 8 | blue;
}
-
+
public void resetColors() {
color = new int[] {
0xff000000, // black
diff --git a/src/org/connectbot/service/TerminalManager.java b/src/org/connectbot/service/TerminalManager.java
index 2ab3d78..58a2280 100644
--- a/src/org/connectbot/service/TerminalManager.java
+++ b/src/org/connectbot/service/TerminalManager.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -53,38 +53,38 @@ import android.util.Log;
* Manager for SSH connections that runs as a background service. This service
* holds a list of currently connected SSH bridges that are ready for connection
* up to a GUI if needed.
- *
+ *
* @author jsharkey
*/
public class TerminalManager extends Service implements BridgeDisconnectedListener {
-
+
public final static String TAG = TerminalManager.class.toString();
-
+
public List<TerminalBridge> bridges = new LinkedList<TerminalBridge>();
public TerminalBridge defaultBridge = null;
-
+
public List<HostBean> disconnected = new LinkedList<HostBean>();
-
+
public Handler disconnectHandler = null;
protected HashMap<String, Object> loadedPubkeys = new HashMap<String, Object>();
-
+
protected Resources res;
-
+
protected HostDatabase hostdb;
protected PubkeyDatabase pubkeydb;
protected SharedPreferences prefs;
private String pref_emulation, pref_scrollback, pref_keymode, pref_memkeys, pref_wifilock;
-
+
private final IBinder binder = new TerminalBinder();
private ConnectivityManager connectivityManager;
private WifiManager.WifiLock wifilock;
-
+
private Timer idleTimer;
private final long IDLE_TIMEOUT = 300000; // 5 minutes
-
+
@Override
public void onCreate() {
Log.i(TAG, "Starting background service");
@@ -94,30 +94,30 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen
pref_keymode = getResources().getString(R.string.pref_keymode);
pref_memkeys = getResources().getString(R.string.pref_memkeys);
pref_wifilock = getResources().getString(R.string.pref_wifilock);
-
+
res = getResources();
-
+
hostdb = new HostDatabase(this);
pubkeydb = new PubkeyDatabase(this);
-
+
// load all marked pubkeys into memory
List<PubkeyBean> pubkeys = pubkeydb.getAllStartPubkeys();
-
+
for (PubkeyBean pubkey : pubkeys) {
try {
PrivateKey privKey = PubkeyUtils.decodePrivate(pubkey.getPrivateKey(), pubkey.getType());
PublicKey pubKey = PubkeyUtils.decodePublic(pubkey.getPublicKey(), pubkey.getType());
Object trileadKey = PubkeyUtils.convertToTrilead(privKey, pubKey);
-
+
loadedPubkeys.put(pubkey.getNickname(), trileadKey);
Log.d(TAG, String.format("Added key '%s' to in-memory cache", pubkey.getNickname()));
} catch (Exception e) {
Log.d(TAG, String.format("Problem adding key '%s' to in-memory cache", pubkey.getNickname()), e);
}
}
-
+
connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
-
+
WifiManager manager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifilock = manager.createWifiLock(TAG);
}
@@ -129,26 +129,26 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen
// disconnect and dispose of any existing bridges
for(TerminalBridge bridge : bridges)
bridge.dispatchDisconnect(true);
-
+
if(hostdb != null) {
hostdb.close();
hostdb = null;
}
-
+
if(pubkeydb != null) {
pubkeydb.close();
pubkeydb = null;
}
-
+
synchronized (this) {
if (idleTimer != null)
idleTimer.cancel();
}
-
+
if (wifilock != null && wifilock.isHeld())
wifilock.release();
}
-
+
/**
* Open a new SSH session using the given parameters.
*/
@@ -157,27 +157,27 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen
if (findBridge(host) != null) {
throw new Exception("Connection already open for that nickname");
}
-
+
TerminalBridge bridge = new TerminalBridge(this, host);
bridge.setOnDisconnectedListener(this);
bridge.startConnection();
bridges.add(bridge);
-
+
// Add a reference to the WifiLock
NetworkInfo info = connectivityManager.getActiveNetworkInfo();
if (isLockingWifi() && info.getType() == ConnectivityManager.TYPE_WIFI) {
Log.d(TAG, "Acquiring WifiLock");
wifilock.acquire();
}
-
+
// also update database with new connected time
touchHost(host);
}
-
+
public String getEmulation() {
return prefs.getString(pref_emulation, "screen");
}
-
+
public int getScrollback() {
int scrollback = 140;
try {
@@ -186,7 +186,7 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen
}
return scrollback;
}
-
+
public boolean isSavingKeys() {
return prefs.getBoolean(pref_memkeys, true);
}
@@ -194,11 +194,11 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen
public String getKeyMode() {
return prefs.getString(pref_keymode, getString(R.string.list_keymode_right)); // "Use right-side keys"
}
-
+
public boolean isLockingWifi() {
return prefs.getBoolean(pref_wifilock, true);
}
-
+
/**
* Open a new SSH session by reading parameters from the given URI. Follows
* format <code>ssh://user@host:port/#nickname</code>
@@ -208,18 +208,18 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen
String username = uri.getUserInfo();
String hostname = uri.getHost();
int port = uri.getPort();
-
+
HostBean host = hostdb.findHost(nickname, username, hostname, port);
-
+
if (host == null) {
Log.d(TAG, String.format("Didn't find existing host (nickname=%s, username=%s, hostname=%s, port=%d)",
nickname, username, hostname, port));
host = new HostBean(nickname, username, hostname, port);
}
-
+
this.openConnection(host);
}
-
+
/**
* Update the last-connected value for the given nickname by passing through
* to {@link HostDatabase}.
@@ -239,7 +239,7 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen
}
return null;
}
-
+
/**
* Called by child bridge when somehow it's been disconnected.
*/
@@ -259,20 +259,20 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen
Message.obtain(disconnectHandler, -1, bridge).sendToTarget();
}
-
+
public boolean isKeyLoaded(String nickname) {
return loadedPubkeys.containsKey(nickname);
}
-
+
public void addKey(String nickname, Object trileadKey) {
loadedPubkeys.remove(nickname);
loadedPubkeys.put(nickname, trileadKey);
}
-
+
public void removeKey(String nickname) {
loadedPubkeys.remove(nickname);
}
-
+
public Object getKey(String nickname) {
return loadedPubkeys.get(nickname);
}
@@ -280,12 +280,12 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen
private void stopWithDelay() {
// TODO add in a way to check whether keys loaded are encrypted and only
// set timer when we have an encrypted key loaded
-
+
if (loadedPubkeys.size() > 0) {
synchronized (this) {
if (idleTimer == null)
idleTimer = new Timer(true);
-
+
idleTimer.schedule(new IdleTask(), IDLE_TIMEOUT);
}
} else {
@@ -293,7 +293,7 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen
stopSelf();
}
}
-
+
protected void stopNow() {
if (bridges.size() == 0)
stopSelf();
@@ -305,41 +305,41 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen
idleTimer = null;
}
}
-
+
public class TerminalBinder extends Binder {
public TerminalManager getService() {
return TerminalManager.this;
}
}
-
+
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "Someone bound to TerminalManager");
-
+
stopIdleTimer();
-
+
// Make sure we stay running to maintain the bridges
startService(new Intent(this, TerminalManager.class));
-
+
return binder;
}
-
+
@Override
public void onRebind(Intent intent) {
super.onRebind(intent);
Log.i(TAG, "Someone rebound to TerminalManager");
-
+
stopIdleTimer();
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "Someone unbound from TerminalManager");
-
+
if (bridges.size() == 0)
stopWithDelay();
-
+
return true;
}
diff --git a/src/org/connectbot/util/Encryptor.java b/src/org/connectbot/util/Encryptor.java
index ebcfc12..f5f6c86 100644
--- a/src/org/connectbot/util/Encryptor.java
+++ b/src/org/connectbot/util/Encryptor.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -19,7 +19,7 @@ package org.connectbot.util;
/**
* This class is from:
- *
+ *
* Encryptor.java
* Copyright 2008 Zach Scrivena
* zachscrivena@gmail.com
@@ -39,166 +39,166 @@ import javax.crypto.spec.SecretKeySpec;
*/
public final class Encryptor
{
- /** name of the character set to use for converting between characters and bytes */
- private static final String CHARSET_NAME = "UTF-8";
-
- /** random number generator algorithm */
- private static final String RNG_ALGORITHM = "SHA1PRNG";
-
- /** message digest algorithm (must be sufficiently long to provide the key and initialization vector) */
- private static final String DIGEST_ALGORITHM = "SHA-256";
-
- /** key algorithm (must be compatible with CIPHER_ALGORITHM) */
- private static final String KEY_ALGORITHM = "AES";
-
- /** cipher algorithm (must be compatible with KEY_ALGORITHM) */
- private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
-
-
- /**
- * Private constructor that should never be called.
- */
- private Encryptor()
- {}
-
-
- /**
- * Encrypt the specified cleartext using the given password.
- * With the correct salt, number of iterations, and password, the decrypt() method reverses
- * the effect of this method.
- * This method generates and uses a random salt, and the user-specified number of iterations
- * and password to create a 16-byte secret key and 16-byte initialization vector.
- * The secret key and initialization vector are then used in the AES-128 cipher to encrypt
- * the given cleartext.
- *
- * @param salt
- * salt that was used in the encryption (to be populated)
- * @param iterations
- * number of iterations to use in salting
- * @param password
- * password to be used for encryption
- * @param cleartext
- * cleartext to be encrypted
- * @return
- * ciphertext
- * @throws Exception
- * on any error encountered in encryption
- */
- public static byte[] encrypt(
- final byte[] salt,
- final int iterations,
- final String password,
- final byte[] cleartext)
- throws Exception
- {
- /* generate salt randomly */
- SecureRandom.getInstance(RNG_ALGORITHM).nextBytes(salt);
-
- /* compute key and initialization vector */
- final MessageDigest shaDigest = MessageDigest.getInstance(DIGEST_ALGORITHM);
- byte[] pw = password.getBytes(CHARSET_NAME);
-
- for (int i = 0; i < iterations; i++)
- {
- /* add salt */
- final byte[] salted = new byte[pw.length + salt.length];
- System.arraycopy(pw, 0, salted, 0, pw.length);
- System.arraycopy(salt, 0, salted, pw.length, salt.length);
- Arrays.fill(pw, (byte) 0x00);
-
- /* compute SHA-256 digest */
- shaDigest.reset();
- pw = shaDigest.digest(salted);
- Arrays.fill(salted, (byte) 0x00);
- }
-
- /* extract the 16-byte key and initialization vector from the SHA-256 digest */
- final byte[] key = new byte[16];
- final byte[] iv = new byte[16];
- System.arraycopy(pw, 0, key, 0, 16);
- System.arraycopy(pw, 16, iv, 0, 16);
- Arrays.fill(pw, (byte) 0x00);
-
- /* perform AES-128 encryption */
- final Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
-
- cipher.init(
- Cipher.ENCRYPT_MODE,
- new SecretKeySpec(key, KEY_ALGORITHM),
- new IvParameterSpec(iv));
-
- Arrays.fill(key, (byte) 0x00);
- Arrays.fill(iv, (byte) 0x00);
-
- return cipher.doFinal(cleartext);
- }
-
-
- /**
- * Decrypt the specified ciphertext using the given password.
- * With the correct salt, number of iterations, and password, this method reverses the effect
- * of the encrypt() method.
- * This method uses the user-specified salt, number of iterations, and password
- * to recreate the 16-byte secret key and 16-byte initialization vector.
- * The secret key and initialization vector are then used in the AES-128 cipher to decrypt
- * the given ciphertext.
- *
- * @param salt
- * salt to be used in decryption
- * @param iterations
- * number of iterations to use in salting
- * @param password
- * password to be used for decryption
- * @param ciphertext
- * ciphertext to be decrypted
- * @return
- * cleartext
- * @throws Exception
- * on any error encountered in decryption
- */
- public static byte[] decrypt(
- final byte[] salt,
- final int iterations,
- final String password,
- final byte[] ciphertext)
- throws Exception
- {
- /* compute key and initialization vector */
- final MessageDigest shaDigest = MessageDigest.getInstance(DIGEST_ALGORITHM);
- byte[] pw = password.getBytes(CHARSET_NAME);
-
- for (int i = 0; i < iterations; i++)
- {
- /* add salt */
- final byte[] salted = new byte[pw.length + salt.length];
- System.arraycopy(pw, 0, salted, 0, pw.length);
- System.arraycopy(salt, 0, salted, pw.length, salt.length);
- Arrays.fill(pw, (byte) 0x00);
-
- /* compute SHA-256 digest */
- shaDigest.reset();
- pw = shaDigest.digest(salted);
- Arrays.fill(salted, (byte) 0x00);
- }
-
- /* extract the 16-byte key and initialization vector from the SHA-256 digest */
- final byte[] key = new byte[16];
- final byte[] iv = new byte[16];
- System.arraycopy(pw, 0, key, 0, 16);
- System.arraycopy(pw, 16, iv, 0, 16);
- Arrays.fill(pw, (byte) 0x00);
-
- /* perform AES-128 decryption */
- final Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
-
- cipher.init(
- Cipher.DECRYPT_MODE,
- new SecretKeySpec(key, KEY_ALGORITHM),
- new IvParameterSpec(iv));
-
- Arrays.fill(key, (byte) 0x00);
- Arrays.fill(iv, (byte) 0x00);
-
- return cipher.doFinal(ciphertext);
- }
-}
+ /** name of the character set to use for converting between characters and bytes */
+ private static final String CHARSET_NAME = "UTF-8";
+
+ /** random number generator algorithm */
+ private static final String RNG_ALGORITHM = "SHA1PRNG";
+
+ /** message digest algorithm (must be sufficiently long to provide the key and initialization vector) */
+ private static final String DIGEST_ALGORITHM = "SHA-256";
+
+ /** key algorithm (must be compatible with CIPHER_ALGORITHM) */
+ private static final String KEY_ALGORITHM = "AES";
+
+ /** cipher algorithm (must be compatible with KEY_ALGORITHM) */
+ private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
+
+
+ /**
+ * Private constructor that should never be called.
+ */
+ private Encryptor()
+ {}
+
+
+ /**
+ * Encrypt the specified cleartext using the given password.
+ * With the correct salt, number of iterations, and password, the decrypt() method reverses
+ * the effect of this method.
+ * This method generates and uses a random salt, and the user-specified number of iterations
+ * and password to create a 16-byte secret key and 16-byte initialization vector.
+ * The secret key and initialization vector are then used in the AES-128 cipher to encrypt
+ * the given cleartext.
+ *
+ * @param salt
+ * salt that was used in the encryption (to be populated)
+ * @param iterations
+ * number of iterations to use in salting
+ * @param password
+ * password to be used for encryption
+ * @param cleartext
+ * cleartext to be encrypted
+ * @return
+ * ciphertext
+ * @throws Exception
+ * on any error encountered in encryption
+ */
+ public static byte[] encrypt(
+ final byte[] salt,
+ final int iterations,
+ final String password,
+ final byte[] cleartext)
+ throws Exception
+ {
+ /* generate salt randomly */
+ SecureRandom.getInstance(RNG_ALGORITHM).nextBytes(salt);
+
+ /* compute key and initialization vector */
+ final MessageDigest shaDigest = MessageDigest.getInstance(DIGEST_ALGORITHM);
+ byte[] pw = password.getBytes(CHARSET_NAME);
+
+ for (int i = 0; i < iterations; i++)
+ {
+ /* add salt */
+ final byte[] salted = new byte[pw.length + salt.length];
+ System.arraycopy(pw, 0, salted, 0, pw.length);
+ System.arraycopy(salt, 0, salted, pw.length, salt.length);
+ Arrays.fill(pw, (byte) 0x00);
+
+ /* compute SHA-256 digest */
+ shaDigest.reset();
+ pw = shaDigest.digest(salted);
+ Arrays.fill(salted, (byte) 0x00);
+ }
+
+ /* extract the 16-byte key and initialization vector from the SHA-256 digest */
+ final byte[] key = new byte[16];
+ final byte[] iv = new byte[16];
+ System.arraycopy(pw, 0, key, 0, 16);
+ System.arraycopy(pw, 16, iv, 0, 16);
+ Arrays.fill(pw, (byte) 0x00);
+
+ /* perform AES-128 encryption */
+ final Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
+
+ cipher.init(
+ Cipher.ENCRYPT_MODE,
+ new SecretKeySpec(key, KEY_ALGORITHM),
+ new IvParameterSpec(iv));
+
+ Arrays.fill(key, (byte) 0x00);
+ Arrays.fill(iv, (byte) 0x00);
+
+ return cipher.doFinal(cleartext);
+ }
+
+
+ /**
+ * Decrypt the specified ciphertext using the given password.
+ * With the correct salt, number of iterations, and password, this method reverses the effect
+ * of the encrypt() method.
+ * This method uses the user-specified salt, number of iterations, and password
+ * to recreate the 16-byte secret key and 16-byte initialization vector.
+ * The secret key and initialization vector are then used in the AES-128 cipher to decrypt
+ * the given ciphertext.
+ *
+ * @param salt
+ * salt to be used in decryption
+ * @param iterations
+ * number of iterations to use in salting
+ * @param password
+ * password to be used for decryption
+ * @param ciphertext
+ * ciphertext to be decrypted
+ * @return
+ * cleartext
+ * @throws Exception
+ * on any error encountered in decryption
+ */
+ public static byte[] decrypt(
+ final byte[] salt,
+ final int iterations,
+ final String password,
+ final byte[] ciphertext)
+ throws Exception
+ {
+ /* compute key and initialization vector */
+ final MessageDigest shaDigest = MessageDigest.getInstance(DIGEST_ALGORITHM);
+ byte[] pw = password.getBytes(CHARSET_NAME);
+
+ for (int i = 0; i < iterations; i++)
+ {
+ /* add salt */
+ final byte[] salted = new byte[pw.length + salt.length];
+ System.arraycopy(pw, 0, salted, 0, pw.length);
+ System.arraycopy(salt, 0, salted, pw.length, salt.length);
+ Arrays.fill(pw, (byte) 0x00);
+
+ /* compute SHA-256 digest */
+ shaDigest.reset();
+ pw = shaDigest.digest(salted);
+ Arrays.fill(salted, (byte) 0x00);
+ }
+
+ /* extract the 16-byte key and initialization vector from the SHA-256 digest */
+ final byte[] key = new byte[16];
+ final byte[] iv = new byte[16];
+ System.arraycopy(pw, 0, key, 0, 16);
+ System.arraycopy(pw, 16, iv, 0, 16);
+ Arrays.fill(pw, (byte) 0x00);
+
+ /* perform AES-128 decryption */
+ final Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
+
+ cipher.init(
+ Cipher.DECRYPT_MODE,
+ new SecretKeySpec(key, KEY_ALGORITHM),
+ new IvParameterSpec(iv));
+
+ Arrays.fill(key, (byte) 0x00);
+ Arrays.fill(iv, (byte) 0x00);
+
+ return cipher.doFinal(ciphertext);
+ }
+}
diff --git a/src/org/connectbot/util/EntropyDialog.java b/src/org/connectbot/util/EntropyDialog.java
index c6dc4e1..bb84418 100644
--- a/src/org/connectbot/util/EntropyDialog.java
+++ b/src/org/connectbot/util/EntropyDialog.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -30,13 +30,13 @@ public class EntropyDialog extends Dialog implements OnEntropyGatheredListener {
this.setContentView(R.layout.dia_gatherentropy);
this.setTitle(R.string.pubkey_gather_entropy);
-
+
((EntropyView) findViewById(R.id.entropy)).addOnEntropyGatheredListener(this);
}
-
+
public EntropyDialog(Context context, View view) {
super(context);
-
+
this.setContentView(view);
this.setTitle(R.string.pubkey_gather_entropy);
diff --git a/src/org/connectbot/util/EntropyView.java b/src/org/connectbot/util/EntropyView.java
index ff6f5ce..778a89a 100644
--- a/src/org/connectbot/util/EntropyView.java
+++ b/src/org/connectbot/util/EntropyView.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -31,113 +31,113 @@ import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
-public class EntropyView extends View {
+public class EntropyView extends View {
private Paint mPaint;
private FontMetrics mFontMetrics;
private boolean mFlipFlop;
private long mLastTime;
private Vector<OnEntropyGatheredListener> listeners;
-
+
private byte[] mEntropy;
private int mEntropyIdx;
private int splitText = 0;
-
+
private float lastX = 0.0f, lastY = 0.0f;
-
+
public EntropyView(Context context) {
super(context);
-
+
setUpEntropy();
}
-
+
public EntropyView(Context context, AttributeSet attrs) {
super(context, attrs);
-
+
setUpEntropy();
}
-
+
private void setUpEntropy() {
- mPaint = new Paint();
- mPaint.setAntiAlias(true);
- mPaint.setTypeface(Typeface.DEFAULT);
- mPaint.setTextAlign(Paint.Align.CENTER);
- mPaint.setTextSize(16);
- mPaint.setColor(Color.WHITE);
- mFontMetrics = mPaint.getFontMetrics();
-
- mEntropy = new byte[20];
- mEntropyIdx = 0;
-
- listeners = new Vector<OnEntropyGatheredListener>();
+ mPaint = new Paint();
+ mPaint.setAntiAlias(true);
+ mPaint.setTypeface(Typeface.DEFAULT);
+ mPaint.setTextAlign(Paint.Align.CENTER);
+ mPaint.setTextSize(16);
+ mPaint.setColor(Color.WHITE);
+ mFontMetrics = mPaint.getFontMetrics();
+
+ mEntropy = new byte[20];
+ mEntropyIdx = 0;
+
+ listeners = new Vector<OnEntropyGatheredListener>();
}
public void addOnEntropyGatheredListener(OnEntropyGatheredListener listener) {
listeners.add(listener);
}
-
+
public void removeOnEntropyGatheredListener(OnEntropyGatheredListener listener) {
listeners.remove(listener);
}
-
- public void onDraw(Canvas c) {
- String prompt = getResources().getString(R.string.pubkey_touch_prompt)
- + " " + (int)(100.0 * (mEntropyIdx / 20.0)) + "% done";
- if (splitText > 0 ||
- mPaint.measureText(prompt) > (getWidth() * 0.8)) {
- if (splitText == 0)
- splitText = prompt.indexOf(" ", prompt.length() / 2);
-
- c.drawText(prompt.substring(0, splitText),
- getWidth() / 2.0f,
- getHeight() / 2.0f + (mPaint.ascent() + mPaint.descent()),
- mPaint);
- c.drawText(prompt.substring(splitText),
- getWidth() / 2.0f,
- getHeight() / 2.0f - (mPaint.ascent() + mPaint.descent()),
- mPaint);
- } else {
- c.drawText(prompt,
- getWidth() / 2.0f,
- getHeight() / 2.0f - (mFontMetrics.ascent + mFontMetrics.descent) / 2,
- mPaint);
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- if (mEntropyIdx >= 20
- || lastX == event.getX()
- || lastY == event.getY())
- return true;
-
- // Only get entropy every 200 milliseconds to ensure the user has moved around.
- long now = System.currentTimeMillis();
- if ((now - mLastTime) < 200)
- return true;
- else
- mLastTime = now;
-
- // Get the lowest 4 bits of each X, Y input and concat to the entropy-gathering
- // string.
- if (mFlipFlop)
- mEntropy[mEntropyIdx++] += (byte)((((int)event.getX() & 0x0F) << 4) | ((int)event.getY() & 0x0F));
- else
- mEntropy[mEntropyIdx++] += (byte)((((int)event.getY() & 0x0F) << 4) | ((int)event.getX() & 0x0F));
-
- mFlipFlop = !mFlipFlop;
- lastX = event.getX();
- lastY = event.getY();
-
- // SHA1PRNG only keeps 20 bytes (160 bits) of entropy.
- if (mEntropyIdx >= 20) {
- for (OnEntropyGatheredListener listener: listeners) {
- listener.onEntropyGathered(mEntropy);
- }
- }
-
- invalidate();
-
- return true;
- }
+
+ public void onDraw(Canvas c) {
+ String prompt = getResources().getString(R.string.pubkey_touch_prompt)
+ + " " + (int)(100.0 * (mEntropyIdx / 20.0)) + "% done";
+ if (splitText > 0 ||
+ mPaint.measureText(prompt) > (getWidth() * 0.8)) {
+ if (splitText == 0)
+ splitText = prompt.indexOf(" ", prompt.length() / 2);
+
+ c.drawText(prompt.substring(0, splitText),
+ getWidth() / 2.0f,
+ getHeight() / 2.0f + (mPaint.ascent() + mPaint.descent()),
+ mPaint);
+ c.drawText(prompt.substring(splitText),
+ getWidth() / 2.0f,
+ getHeight() / 2.0f - (mPaint.ascent() + mPaint.descent()),
+ mPaint);
+ } else {
+ c.drawText(prompt,
+ getWidth() / 2.0f,
+ getHeight() / 2.0f - (mFontMetrics.ascent + mFontMetrics.descent) / 2,
+ mPaint);
+ }
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (mEntropyIdx >= 20
+ || lastX == event.getX()
+ || lastY == event.getY())
+ return true;
+
+ // Only get entropy every 200 milliseconds to ensure the user has moved around.
+ long now = System.currentTimeMillis();
+ if ((now - mLastTime) < 200)
+ return true;
+ else
+ mLastTime = now;
+
+ // Get the lowest 4 bits of each X, Y input and concat to the entropy-gathering
+ // string.
+ if (mFlipFlop)
+ mEntropy[mEntropyIdx++] += (byte)((((int)event.getX() & 0x0F) << 4) | ((int)event.getY() & 0x0F));
+ else
+ mEntropy[mEntropyIdx++] += (byte)((((int)event.getY() & 0x0F) << 4) | ((int)event.getX() & 0x0F));
+
+ mFlipFlop = !mFlipFlop;
+ lastX = event.getX();
+ lastY = event.getY();
+
+ // SHA1PRNG only keeps 20 bytes (160 bits) of entropy.
+ if (mEntropyIdx >= 20) {
+ for (OnEntropyGatheredListener listener: listeners) {
+ listener.onEntropyGathered(mEntropy);
+ }
+ }
+
+ invalidate();
+
+ return true;
+ }
}
diff --git a/src/org/connectbot/util/HelpTopicView.java b/src/org/connectbot/util/HelpTopicView.java
index 84216ae..2619699 100644
--- a/src/org/connectbot/util/HelpTopicView.java
+++ b/src/org/connectbot/util/HelpTopicView.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -43,20 +43,20 @@ public class HelpTopicView extends WebView {
super(context);
initialize();
}
-
+
private void initialize() {
WebSettings wSet = getSettings();
wSet.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
wSet.setUseWideViewPort(false);
}
-
+
public HelpTopicView setTopic(String topic) {
String path = String.format("file:///android_asset/%s/%s%s",
HelpActivity.HELPDIR, topic, HelpActivity.SUFFIX);
loadUrl(path);
-
+
computeScroll();
-
+
return this;
}
}
diff --git a/src/org/connectbot/util/HostDatabase.java b/src/org/connectbot/util/HostDatabase.java
index 550f88e..2575355 100644
--- a/src/org/connectbot/util/HostDatabase.java
+++ b/src/org/connectbot/util/HostDatabase.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -36,16 +36,16 @@ import android.util.Log;
/**
* Contains information about various SSH hosts, include public hostkey if known
* from previous sessions.
- *
+ *
* @author jsharkey
*/
public class HostDatabase extends SQLiteOpenHelper {
-
+
public final static String TAG = HostDatabase.class.toString();
-
+
public final static String DB_NAME = "hosts";
public final static int DB_VERSION = 15;
-
+
public final static String TABLE_HOSTS = "hosts";
public final static String FIELD_HOST_NICKNAME = "nickname";
public final static String FIELD_HOST_USERNAME = "username";
@@ -61,7 +61,7 @@ public class HostDatabase extends SQLiteOpenHelper {
public final static String FIELD_HOST_WANTSESSION = "wantsession";
public final static String FIELD_HOST_COMPRESSION = "compression";
public final static String FIELD_HOST_ENCODING = "encoding";
-
+
public final static String TABLE_PORTFORWARDS = "portforwards";
public final static String FIELD_PORTFORWARD_HOSTID = "hostid";
public final static String FIELD_PORTFORWARD_NICKNAME = "nickname";
@@ -74,19 +74,19 @@ public class HostDatabase extends SQLiteOpenHelper {
public final static String COLOR_GREEN = "green";
public final static String COLOR_BLUE = "blue";
public final static String COLOR_GRAY = "gray";
-
+
public final static String PORTFORWARD_LOCAL = "local";
public final static String PORTFORWARD_REMOTE = "remote";
public final static String PORTFORWARD_DYNAMIC4 = "dynamic4";
public final static String PORTFORWARD_DYNAMIC5 = "dynamic5";
-
+
public final static String ENCODING_ASCII = "ASCII";
public final static String ENCODING_UTF8 = "UTF-8";
public final static String ENCODING_ISO88591 = "ISO8859_1";
public final static long PUBKEYID_NEVER = -2;
public final static long PUBKEYID_ANY = -1;
-
+
public HostDatabase(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
@@ -113,7 +113,7 @@ public class HostDatabase extends SQLiteOpenHelper {
//this.createHost(db, "connectbot@bravo", "connectbot", "192.168.254.230", 22, COLOR_GRAY);
//this.createHost(db, "cron@server.example.com", "cron", "server.example.com", 22, COLOR_GRAY, PUBKEYID_ANY);
//this.createHost(db, "backup@example.net", "backup", "example.net", 22, COLOR_BLUE, PUBKEYID_ANY);
-
+
db.execSQL("CREATE TABLE " + TABLE_PORTFORWARDS
+ " (_id INTEGER PRIMARY KEY, "
+ FIELD_PORTFORWARD_HOSTID + " INTEGER, "
@@ -133,7 +133,7 @@ public class HostDatabase extends SQLiteOpenHelper {
onCreate(db);
return;
}
-
+
switch (oldVersion) {
case 10:
db.execSQL("ALTER TABLE " + TABLE_HOSTS
@@ -158,7 +158,7 @@ public class HostDatabase extends SQLiteOpenHelper {
+ " ADD COLUMN " + FIELD_HOST_ENCODING + " TEXT DEFAULT '" + ENCODING_ASCII + "'");
}
}
-
+
/**
* Touch a specific host to update its "last connected" field.
* @param nickname Nickname field of host to update
@@ -166,41 +166,41 @@ public class HostDatabase extends SQLiteOpenHelper {
public void touchHost(HostBean host) {
SQLiteDatabase db = this.getWritableDatabase();
long now = System.currentTimeMillis() / 1000;
-
+
ContentValues values = new ContentValues();
values.put(FIELD_HOST_LASTCONNECT, now);
-
+
db.update(TABLE_HOSTS, values, "_id = ?", new String[] { String.valueOf(host.getId()) });
-
+
db.close();
}
-
+
/**
* Create a new host using the given parameters.
*/
public HostBean saveHost(HostBean host) {
SQLiteDatabase db = this.getWritableDatabase();
-
+
long id = db.insert(TABLE_HOSTS, null, host.getValues());
db.close();
host.setId(id);
-
+
return host;
}
-
+
/**
* Delete a specific host by its <code>_id</code> value.
*/
public void deleteHost(HostBean host) {
if (host.getId() < 0)
return;
-
+
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_HOSTS, "_id = ?", new String[] { String.valueOf(host.getId()) });
db.close();
}
-
+
/**
* Return a cursor that contains information about all known hosts.
* @param sortColors If true, sort by color, otherwise sort by nickname.
@@ -208,9 +208,9 @@ public class HostDatabase extends SQLiteOpenHelper {
public List<HostBean> getHosts(boolean sortColors) {
String sortField = sortColors ? FIELD_HOST_COLOR : FIELD_HOST_NICKNAME;
SQLiteDatabase db = this.getReadableDatabase();
-
+
List<HostBean> hosts = new LinkedList<HostBean>();
-
+
Cursor c = db.query(TABLE_HOSTS, null, null, null, null, null, sortField + " ASC");
final int COL_ID = c.getColumnIndexOrThrow("_id"),
@@ -226,10 +226,10 @@ public class HostDatabase extends SQLiteOpenHelper {
COL_WANTSESSION = c.getColumnIndexOrThrow(FIELD_HOST_WANTSESSION),
COL_COMPRESSION = c.getColumnIndexOrThrow(FIELD_HOST_COMPRESSION),
COL_ENCODING = c.getColumnIndexOrThrow(FIELD_HOST_ENCODING);
-
+
while (c.moveToNext()) {
HostBean host = new HostBean();
-
+
host.setId(c.getLong(COL_ID));
host.setNickname(c.getString(COL_NICKNAME));
host.setUsername(c.getString(COL_USERNAME));
@@ -243,16 +243,16 @@ public class HostDatabase extends SQLiteOpenHelper {
host.setWantSession(Boolean.valueOf(c.getString(COL_WANTSESSION)));
host.setCompression(Boolean.valueOf(c.getString(COL_COMPRESSION)));
host.setEncoding(c.getString(COL_ENCODING));
-
+
hosts.add(host);
}
-
+
c.close();
db.close();
-
+
return hosts;
}
-
+
/**
* @param nickname
* @param username
@@ -263,7 +263,7 @@ public class HostDatabase extends SQLiteOpenHelper {
public HostBean findHost(String nickname, String username, String hostname,
int port) {
SQLiteDatabase db = this.getReadableDatabase();
-
+
Cursor c = db.query(TABLE_HOSTS, null,
FIELD_HOST_NICKNAME + " = ? AND " +
FIELD_HOST_USERNAME + " = ? AND " +
@@ -271,18 +271,18 @@ public class HostDatabase extends SQLiteOpenHelper {
FIELD_HOST_PORT + " = ?",
new String[] { nickname, username, hostname, String.valueOf(port) },
null, null, null);
-
+
HostBean host = null;
-
+
if (c != null) {
if (c.moveToFirst())
host = createHostBean(c);
-
+
c.close();
}
-
+
db.close();
-
+
return host;
}
@@ -292,28 +292,28 @@ public class HostDatabase extends SQLiteOpenHelper {
*/
public HostBean findHostById(long hostId) {
SQLiteDatabase db = this.getReadableDatabase();
-
+
Cursor c = db.query(TABLE_HOSTS, null,
"_id = ?", new String[] { String.valueOf(hostId) },
null, null, null);
-
+
HostBean host = null;
-
+
if (c != null) {
if (c.moveToFirst())
host = createHostBean(c);
-
+
c.close();
}
-
+
db.close();
-
+
return host;
}
-
+
private HostBean createHostBean(Cursor c) {
HostBean host = new HostBean();
-
+
host.setId(c.getLong(c.getColumnIndexOrThrow("_id")));
host.setNickname(c.getString(c.getColumnIndexOrThrow(FIELD_HOST_NICKNAME)));
host.setUsername(c.getString(c.getColumnIndexOrThrow(FIELD_HOST_USERNAME)));
@@ -327,39 +327,39 @@ public class HostDatabase extends SQLiteOpenHelper {
host.setWantSession(Boolean.valueOf(c.getString(c.getColumnIndexOrThrow(FIELD_HOST_WANTSESSION))));
host.setCompression(Boolean.valueOf(c.getString(c.getColumnIndexOrThrow(FIELD_HOST_COMPRESSION))));
host.setEncoding(c.getString(c.getColumnIndexOrThrow(FIELD_HOST_ENCODING)));
-
+
return host;
}
/**
* Record the given hostkey into database under this nickname.
* @param hostname
- * @param port
+ * @param port
* @param hostkeyalgo
* @param hostkey
*/
public void saveKnownHost(String hostname, int port, String hostkeyalgo, byte[] hostkey) {
SQLiteDatabase db = this.getReadableDatabase();
-
+
ContentValues values = new ContentValues();
values.put(FIELD_HOST_HOSTKEYALGO, hostkeyalgo);
values.put(FIELD_HOST_HOSTKEY, hostkey);
-
+
db.update(TABLE_HOSTS, values,
FIELD_HOST_HOSTNAME + " = ? AND " + FIELD_HOST_PORT + " = ?",
new String[] { hostname, String.valueOf(port) });
Log.d(TAG, String.format("Finished saving hostkey information for '%s'", hostname));
-
+
db.close();
}
-
+
/**
* Build list of known hosts for Trilead library.
* @return
*/
public KnownHosts getKnownHosts() {
KnownHosts known = new KnownHosts();
-
+
SQLiteDatabase db = this.getReadableDatabase();
Cursor c = db.query(TABLE_HOSTS, new String[] { FIELD_HOST_HOSTNAME,
FIELD_HOST_PORT, FIELD_HOST_HOSTKEYALGO, FIELD_HOST_HOSTKEY },
@@ -370,28 +370,28 @@ public class HostDatabase extends SQLiteOpenHelper {
COL_PORT = c.getColumnIndexOrThrow(FIELD_HOST_PORT),
COL_HOSTKEYALGO = c.getColumnIndexOrThrow(FIELD_HOST_HOSTKEYALGO),
COL_HOSTKEY = c.getColumnIndexOrThrow(FIELD_HOST_HOSTKEY);
-
+
while (c.moveToNext()) {
String hostname = c.getString(COL_HOSTNAME),
hostkeyalgo = c.getString(COL_HOSTKEYALGO);
int port = c.getInt(COL_PORT);
byte[] hostkey = c.getBlob(COL_HOSTKEY);
-
+
if (hostkeyalgo == null || hostkeyalgo.length() == 0) continue;
if (hostkey == null || hostkey.length == 0) continue;
-
+
try {
known.addHostkey(new String[] { String.format("%s:%d", hostname, port) }, hostkeyalgo, hostkey);
} catch(Exception e) {
Log.e(TAG, "Problem while adding a known host from database", e);
}
}
-
+
c.close();
}
-
+
db.close();
-
+
return known;
}
@@ -401,31 +401,31 @@ public class HostDatabase extends SQLiteOpenHelper {
*/
public void stopUsingPubkey(long pubkeyId) {
if (pubkeyId < 0) return;
-
+
SQLiteDatabase db = this.getWritableDatabase();
-
+
ContentValues values = new ContentValues();
values.put(FIELD_HOST_PUBKEYID, PUBKEYID_ANY);
-
+
db.update(TABLE_HOSTS, values, FIELD_HOST_PUBKEYID + " = ?", new String[] { String.valueOf(pubkeyId) });
db.close();
-
+
Log.d(TAG, String.format("Set all hosts using pubkey id %d to -1", pubkeyId));
}
-
+
/*
* Methods for dealing with port forwards attached to hosts
*/
-
+
/**
* Returns a list of all the port forwards associated with a particular host ID.
* @param host the host for which we want the port forward list
- * @return port forwards associated with host ID
+ * @return port forwards associated with host ID
*/
public List<PortForwardBean> getPortForwardsForHost(HostBean host) {
SQLiteDatabase db = this.getReadableDatabase();
List<PortForwardBean> portForwards = new LinkedList<PortForwardBean>();
-
+
Cursor c = db.query(TABLE_PORTFORWARDS, new String[] {
"_id", FIELD_PORTFORWARD_NICKNAME, FIELD_PORTFORWARD_TYPE, FIELD_PORTFORWARD_SOURCEPORT,
FIELD_PORTFORWARD_DESTADDR, FIELD_PORTFORWARD_DESTPORT },
@@ -443,10 +443,10 @@ public class HostDatabase extends SQLiteOpenHelper {
c.getInt(5));
portForwards.add(pfb);
}
-
+
c.close();
db.close();
-
+
return portForwards;
}
@@ -456,20 +456,20 @@ public class HostDatabase extends SQLiteOpenHelper {
* @return true on success
*/
public boolean savePortForward(PortForwardBean pfb) {
- boolean success = false;
+ boolean success = false;
SQLiteDatabase db = this.getWritableDatabase();
if (pfb.getId() < 0) {
long id = db.insert(TABLE_PORTFORWARDS, null, pfb.getValues());
pfb.setId(id);
success = true;
- } else {
+ } else {
if (db.update(TABLE_PORTFORWARDS, pfb.getValues(), "_id = ?", new String[] { String.valueOf(pfb.getId()) }) > 0)
success = true;
}
-
+
db.close();
-
+
return success;
}
@@ -480,7 +480,7 @@ public class HostDatabase extends SQLiteOpenHelper {
public void deletePortForward(PortForwardBean pfb) {
if (pfb.getId() < 0)
return;
-
+
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_PORTFORWARDS, "_id = ?", new String[] { String.valueOf(pfb.getId()) });
db.close();
diff --git a/src/org/connectbot/util/OnEntropyGatheredListener.java b/src/org/connectbot/util/OnEntropyGatheredListener.java
index 9dd2e44..6c31747 100644
--- a/src/org/connectbot/util/OnEntropyGatheredListener.java
+++ b/src/org/connectbot/util/OnEntropyGatheredListener.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
diff --git a/src/org/connectbot/util/PubkeyDatabase.java b/src/org/connectbot/util/PubkeyDatabase.java
index 9dd24f8..eb437ef 100644
--- a/src/org/connectbot/util/PubkeyDatabase.java
+++ b/src/org/connectbot/util/PubkeyDatabase.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -32,15 +32,15 @@ import android.database.sqlite.SQLiteOpenHelper;
/**
* Public Key Encryption database. Contains private and public key pairs
* for public key authentication.
- *
+ *
* @author Kenny Root
*/
-public class PubkeyDatabase extends SQLiteOpenHelper {
+public class PubkeyDatabase extends SQLiteOpenHelper {
public final static String TAG = PubkeyDatabase.class.toString();
-
+
public final static String DB_NAME = "pubkeys";
public final static int DB_VERSION = 1;
-
+
public final static String TABLE_PUBKEYS = "pubkeys";
public final static String FIELD_PUBKEY_NICKNAME = "nickname";
public final static String FIELD_PUBKEY_TYPE = "type";
@@ -48,16 +48,16 @@ public class PubkeyDatabase extends SQLiteOpenHelper {
public final static String FIELD_PUBKEY_PUBLIC = "public";
public final static String FIELD_PUBKEY_ENCRYPTED = "encrypted";
public final static String FIELD_PUBKEY_STARTUP = "startup";
-
+
public final static String KEY_TYPE_RSA = "RSA",
KEY_TYPE_DSA = "DSA",
KEY_TYPE_IMPORTED = "IMPORTED";
-
+
private Context context;
public PubkeyDatabase(Context context) {
super(context, DB_NAME, null, DB_VERSION);
-
+
this.context = context;
}
@@ -77,7 +77,7 @@ public class PubkeyDatabase extends SQLiteOpenHelper {
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
-
+
/**
* Delete a specific host by its <code>_id</code> value.
*/
@@ -85,12 +85,12 @@ public class PubkeyDatabase extends SQLiteOpenHelper {
HostDatabase hostdb = new HostDatabase(context);
hostdb.stopUsingPubkey(pubkey.getId());
hostdb.close();
-
+
SQLiteDatabase db = getWritableDatabase();
db.delete(TABLE_PUBKEYS, "_id = ?", new String[] { Long.toString(pubkey.getId()) });
db.close();
}
-
+
/**
* Return a cursor that contains information about all known hosts.
*/
@@ -102,22 +102,22 @@ public class PubkeyDatabase extends SQLiteOpenHelper {
FIELD_PUBKEY_PUBLIC, FIELD_PUBKEY_ENCRYPTED, FIELD_PUBKEY_STARTUP },
null, null, null, null, null);
}*/
-
+
public List<PubkeyBean> allPubkeys() {
return getPubkeys(null, null);
}
-
+
public List<PubkeyBean> getAllStartPubkeys() {
return getPubkeys(FIELD_PUBKEY_STARTUP + " = 1 AND " + FIELD_PUBKEY_ENCRYPTED + " = 0", null);
}
-
+
private List<PubkeyBean> getPubkeys(String selection, String[] selectionArgs) {
SQLiteDatabase db = getReadableDatabase();
List<PubkeyBean> pubkeys = new LinkedList<PubkeyBean>();
Cursor c = db.query(TABLE_PUBKEYS, null, selection, selectionArgs, null, null, null);
-
+
if (c != null) {
final int COL_ID = c.getColumnIndexOrThrow("_id"),
COL_NICKNAME = c.getColumnIndexOrThrow(FIELD_PUBKEY_NICKNAME),
@@ -126,10 +126,10 @@ public class PubkeyDatabase extends SQLiteOpenHelper {
COL_PUBLIC = c.getColumnIndexOrThrow(FIELD_PUBKEY_PUBLIC),
COL_ENCRYPTED = c.getColumnIndexOrThrow(FIELD_PUBKEY_ENCRYPTED),
COL_STARTUP = c.getColumnIndexOrThrow(FIELD_PUBKEY_STARTUP);
-
+
while (c.moveToNext()) {
PubkeyBean pubkey = new PubkeyBean();
-
+
pubkey.setId(c.getLong(COL_ID));
pubkey.setNickname(c.getString(COL_NICKNAME));
pubkey.setType(c.getString(COL_TYPE));
@@ -137,46 +137,46 @@ public class PubkeyDatabase extends SQLiteOpenHelper {
pubkey.setPublicKey(c.getBlob(COL_PUBLIC));
pubkey.setEncrypted(c.getInt(COL_ENCRYPTED) > 0);
pubkey.setStartup(c.getInt(COL_STARTUP) > 0);
-
+
pubkeys.add(pubkey);
}
-
+
c.close();
}
-
+
db.close();
-
+
return pubkeys;
}
-
+
/**
* @param hostId
* @return
*/
public PubkeyBean findPubkeyById(long pubkeyId) {
SQLiteDatabase db = getReadableDatabase();
-
+
Cursor c = db.query(TABLE_PUBKEYS, null,
"_id = ?", new String[] { String.valueOf(pubkeyId) },
null, null, null);
-
+
PubkeyBean pubkey = null;
-
+
if (c != null) {
if (c.moveToFirst())
pubkey = createPubkeyBean(c);
-
+
c.close();
}
-
+
db.close();
-
+
return pubkey;
}
-
+
private PubkeyBean createPubkeyBean(Cursor c) {
PubkeyBean pubkey = new PubkeyBean();
-
+
pubkey.setId(c.getLong(c.getColumnIndexOrThrow("_id")));
pubkey.setNickname(c.getString(c.getColumnIndexOrThrow(FIELD_PUBKEY_NICKNAME)));
pubkey.setType(c.getString(c.getColumnIndexOrThrow(FIELD_PUBKEY_TYPE)));
@@ -184,7 +184,7 @@ public class PubkeyDatabase extends SQLiteOpenHelper {
pubkey.setPublicKey(c.getBlob(c.getColumnIndexOrThrow(FIELD_PUBKEY_PUBLIC)));
pubkey.setEncrypted(c.getInt(c.getColumnIndexOrThrow(FIELD_PUBKEY_ENCRYPTED)) > 0);
pubkey.setStartup(c.getInt(c.getColumnIndexOrThrow(FIELD_PUBKEY_STARTUP)) > 0);
-
+
return pubkey;
}
@@ -194,68 +194,68 @@ public class PubkeyDatabase extends SQLiteOpenHelper {
*/
public List<CharSequence> allValues(String column) {
List<CharSequence> list = new LinkedList<CharSequence>();
-
+
SQLiteDatabase db = this.getReadableDatabase();
Cursor c = db.query(TABLE_PUBKEYS, new String[] { "_id", column },
null, null, null, null, "_id ASC");
-
+
if (c != null) {
int COL = c.getColumnIndexOrThrow(column);
-
+
while (c.moveToNext())
list.add(c.getString(COL));
-
+
c.close();
}
-
+
db.close();
-
+
return list;
}
public String getNickname(long id) {
String nickname = null;
-
+
SQLiteDatabase db = this.getReadableDatabase();
Cursor c = db.query(TABLE_PUBKEYS, new String[] { "_id",
FIELD_PUBKEY_NICKNAME }, "_id = ?",
new String[] { Long.toString(id) }, null, null, null);
-
+
if (c != null) {
if (c.moveToFirst())
nickname = c.getString(c.getColumnIndexOrThrow(FIELD_PUBKEY_NICKNAME));
-
+
c.close();
}
-
+
db.close();
-
+
return nickname;
}
-
-/*
+
+/*
public void setOnStart(long id, boolean onStart) {
-
+
SQLiteDatabase db = this.getWritableDatabase();
-
+
ContentValues values = new ContentValues();
values.put(FIELD_PUBKEY_STARTUP, onStart ? 1 : 0);
-
+
db.update(TABLE_PUBKEYS, values, "_id = ?", new String[] { Long.toString(id) });
-
+
}
-
+
public boolean changePassword(long id, String oldPassword, String newPassword) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException {
- SQLiteDatabase db = this.getWritableDatabase();
-
+ SQLiteDatabase db = this.getWritableDatabase();
+
Cursor c = db.query(TABLE_PUBKEYS, new String[] { FIELD_PUBKEY_TYPE,
FIELD_PUBKEY_PRIVATE, FIELD_PUBKEY_ENCRYPTED },
"_id = ?", new String[] { String.valueOf(id) },
null, null, null);
-
+
if (!c.moveToFirst())
return false;
-
+
String keyType = c.getString(0);
byte[] encPriv = c.getBlob(1);
c.close();
@@ -270,12 +270,12 @@ public class PubkeyDatabase extends SQLiteOpenHelper {
} catch (InvalidKeySpecException e) {
return false;
}
-
+
ContentValues values = new ContentValues();
values.put(FIELD_PUBKEY_PRIVATE, PubkeyUtils.getEncodedPrivate(priv, newPassword));
values.put(FIELD_PUBKEY_ENCRYPTED, newPassword.length() > 0 ? 1 : 0);
db.update(TABLE_PUBKEYS, values, "_id = ?", new String[] { String.valueOf(id) });
-
+
return true;
}
*/
@@ -286,22 +286,22 @@ public class PubkeyDatabase extends SQLiteOpenHelper {
public PubkeyBean savePubkey(PubkeyBean pubkey) {
SQLiteDatabase db = this.getWritableDatabase();
boolean success = false;
-
+
ContentValues values = pubkey.getValues();
-
+
if (pubkey.getId() > 0) {
values.remove("_id");
if (db.update(TABLE_PUBKEYS, values, "_id = ?", new String[] { String.valueOf(pubkey.getId()) }) > 0)
success = true;
}
-
+
if (!success) {
long id = db.insert(TABLE_PUBKEYS, null, pubkey.getValues());
pubkey.setId(id);
}
-
+
db.close();
-
+
return pubkey;
}
}
diff --git a/src/org/connectbot/util/PubkeyUtils.java b/src/org/connectbot/util/PubkeyUtils.java
index d6bf332..a564c5f 100644
--- a/src/org/connectbot/util/PubkeyUtils.java
+++ b/src/org/connectbot/util/PubkeyUtils.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -65,13 +65,13 @@ import com.trilead.ssh2.signature.RSASHA1Verify;
public class PubkeyUtils {
public static final String PKCS8_START = "-----BEGIN PRIVATE KEY-----";
public static final String PKCS8_END = "-----END PRIVATE KEY-----";
-
+
// Size in bytes of salt to use.
private static final int SALT_SIZE = 8;
-
+
// Number of iterations for password hashing. PKCS#5 recommends 1000
private static final int ITERATIONS = 1000;
-
+
public static String formatKey(Key key){
String algo = key.getAlgorithm();
String fmt = key.getFormat();
@@ -79,7 +79,7 @@ public class PubkeyUtils {
return "Key[algorithm=" + algo + ", format=" + fmt +
", bytes=" + encoded.length + "]";
}
-
+
public static String describeKey(Key key, boolean encrypted) {
String desc = null;
if (key instanceof RSAPublicKey) {
@@ -90,24 +90,24 @@ public class PubkeyUtils {
} else {
desc = "Unknown Key Type";
}
-
+
if (encrypted)
desc += " (encrypted)";
-
+
return desc;
}
-
+
public static byte[] sha256(byte[] data) throws NoSuchAlgorithmException {
return MessageDigest.getInstance("SHA-256").digest(data);
}
-
+
public static byte[] cipher(int mode, byte[] data, byte[] secret) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
SecretKeySpec secretKeySpec = new SecretKeySpec(sha256(secret), "AES");
Cipher c = Cipher.getInstance("AES");
c.init(mode, secretKeySpec);
return c.doFinal(data);
- }
-
+ }
+
public static byte[] encrypt(byte[] cleartext, String secret) throws Exception {
byte[] salt = new byte[SALT_SIZE];
@@ -123,15 +123,15 @@ public class PubkeyUtils {
return complete;
}
-
+
public static byte[] decrypt(byte[] complete, String secret) throws Exception {
try {
byte[] salt = new byte[SALT_SIZE];
byte[] ciphertext = new byte[complete.length - salt.length];
-
+
System.arraycopy(complete, 0, salt, 0, salt.length);
System.arraycopy(complete, salt.length, ciphertext, 0, ciphertext.length);
-
+
return Encryptor.decrypt(salt, ITERATIONS, secret, ciphertext);
} catch (Exception e) {
Log.d("decrypt", "Could not decrypt with new method", e);
@@ -139,41 +139,41 @@ public class PubkeyUtils {
return cipher(Cipher.DECRYPT_MODE, complete, secret.getBytes());
}
}
-
+
public static byte[] getEncodedPublic(PublicKey pk) {
return new X509EncodedKeySpec(pk.getEncoded()).getEncoded();
}
-
+
public static byte[] getEncodedPrivate(PrivateKey pk) {
return new PKCS8EncodedKeySpec(pk.getEncoded()).getEncoded();
}
-
+
public static byte[] getEncodedPrivate(PrivateKey pk, String secret) throws Exception {
if (secret.length() > 0)
return encrypt(getEncodedPrivate(pk), secret);
else
return getEncodedPrivate(pk);
}
-
+
public static PrivateKey decodePrivate(byte[] encoded, String keyType) throws NoSuchAlgorithmException, InvalidKeySpecException {
PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(encoded);
KeyFactory kf = KeyFactory.getInstance(keyType);
return kf.generatePrivate(privKeySpec);
}
-
+
public static PrivateKey decodePrivate(byte[] encoded, String keyType, String secret) throws Exception {
if (secret != null && secret.length() > 0)
return decodePrivate(decrypt(encoded, secret), keyType);
else
return decodePrivate(encoded, keyType);
}
-
+
public static PublicKey decodePublic(byte[] encoded, String keyType) throws NoSuchAlgorithmException, InvalidKeySpecException {
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encoded);
KeyFactory kf = KeyFactory.getInstance(keyType);
return kf.generatePublic(pubKeySpec);
}
-
+
public static KeyPair recoverKeyPair(byte[] encoded) throws NoSuchAlgorithmException, InvalidKeySpecException {
KeySpec privKeySpec = new PKCS8EncodedKeySpec(encoded);
KeySpec pubKeySpec;
@@ -208,11 +208,11 @@ public class PubkeyUtils {
return new KeyPair(pub, priv);
}
-
+
/*
* Trilead compatibility methods
*/
-
+
public static Object convertToTrilead(PublicKey pk) {
if (pk instanceof RSAPublicKey) {
return new com.trilead.ssh2.signature.RSAPublicKey(
@@ -223,10 +223,10 @@ public class PubkeyUtils {
return new com.trilead.ssh2.signature.DSAPublicKey(
dp.getP(), dp.getQ(), dp.getG(), ((DSAPublicKey) pk).getY());
}
-
+
throw new IllegalArgumentException("PublicKey is not RSA or DSA format");
}
-
+
public static Object convertToTrilead(PrivateKey priv, PublicKey pub) {
if (priv instanceof RSAPrivateKey) {
return new com.trilead.ssh2.signature.RSAPrivateKey(
@@ -239,14 +239,14 @@ public class PubkeyUtils {
dp.getP(), dp.getQ(), dp.getG(), ((DSAPublicKey) pub).getY(),
((DSAPrivateKey) priv).getX());
}
-
+
throw new IllegalArgumentException("Key is not RSA or DSA format");
}
-
+
/*
- * OpenSSH compatibility methods
+ * OpenSSH compatibility methods
*/
-
+
public static String convertToOpenSSHFormat(PublicKey pk, String nickname) throws IOException, InvalidKeyException {
if (nickname == null)
nickname = "connectbot@android";
@@ -262,11 +262,11 @@ public class PubkeyUtils {
(com.trilead.ssh2.signature.DSAPublicKey)convertToTrilead(pk))));
return data + " " + nickname;
}
-
+
throw new InvalidKeyException("Unknown key type");
}
-
- public static String exportPEM(PrivateKey key, String secret) throws NoSuchAlgorithmException, InvalidParameterSpecException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, InvalidKeySpecException, IllegalBlockSizeException, IOException {
+
+ public static String exportPEM(PrivateKey key, String secret) throws NoSuchAlgorithmException, InvalidParameterSpecException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, InvalidKeySpecException, IllegalBlockSizeException, IOException {
StringBuilder sb = new StringBuilder();
byte[] data = key.getEncoded();
@@ -278,24 +278,24 @@ public class PubkeyUtils {
byte[] salt = new byte[8];
SecureRandom random = new SecureRandom();
random.nextBytes(salt);
-
+
PBEParameterSpec defParams = new PBEParameterSpec(salt, 1);
AlgorithmParameters params = AlgorithmParameters.getInstance(key.getAlgorithm());
-
+
params.init(defParams);
-
+
PBEKeySpec pbeSpec = new PBEKeySpec(secret.toCharArray());
-
+
SecretKeyFactory keyFact = SecretKeyFactory.getInstance(key.getAlgorithm());
Cipher cipher = Cipher.getInstance(key.getAlgorithm());
cipher.init(Cipher.WRAP_MODE, keyFact.generateSecret(pbeSpec), params);
-
+
byte[] wrappedKey = cipher.wrap(key);
-
+
EncryptedPrivateKeyInfo pinfo = new EncryptedPrivateKeyInfo(params, wrappedKey);
-
+
data = pinfo.getEncoded();
-
+
sb.append("Proc-Type: 4,ENCRYPTED\n");
sb.append("DEK-Info: DES-EDE3-CBC,");
sb.append(encodeHex(salt));
@@ -314,18 +314,18 @@ public class PubkeyUtils {
return sb.toString();
}
-
- final static private char hexDigit[] = { '0', '1', '2', '3', '4', '5', '6',
+
+ final static private char hexDigit[] = { '0', '1', '2', '3', '4', '5', '6',
'7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
- private static String encodeHex(byte[] bytes) {
- char[] hex = new char[bytes.length * 2];
-
- int i = 0;
- for (byte b : bytes) {
- hex[i++] = hexDigit[(b >> 4) & 0x0f];
- hex[i++] = hexDigit[b & 0x0f];
- }
-
- return new String(hex);
- }
+ private static String encodeHex(byte[] bytes) {
+ char[] hex = new char[bytes.length * 2];
+
+ int i = 0;
+ for (byte b : bytes) {
+ hex[i++] = hexDigit[(b >> 4) & 0x0f];
+ hex[i++] = hexDigit[b & 0x0f];
+ }
+
+ return new String(hex);
+ }
}
diff --git a/src/org/connectbot/util/UpdateHelper.java b/src/org/connectbot/util/UpdateHelper.java
index b5061e3..633b801 100644
--- a/src/org/connectbot/util/UpdateHelper.java
+++ b/src/org/connectbot/util/UpdateHelper.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -45,34 +45,34 @@ import android.util.Log;
* Helper class that checks for updates to this application. On construction, it
* spawns a background thread that checks for any app updates. If available,
* shows a dialog to the user, prompting them to visit Market for the upgrade.
- *
+ *
* <b>Be sure to change the UPDATE_URL field before using this class.</b> Then
* place a text file at that URL containing JSON data in the format:
- *
+ *
* <code>{"versionCode": 110, "features": "Brand new interface with over
* 9,000 improvements.", "target": "search?q=searchterms"}</code>
- *
+ *
* Which should contain information about your newest version. The
* <code>target</code> field is used to build an Intent that launches Market on
* the device, simply be prefixing it with <code>market://</code>. If you know
* your exact Market ID, you could use the value
* <code>details?id=yourexactmarketid</code>
- *
+ *
* If you're looking for an advanced version-checking system that offers more
* customization, check out Veecheck: http://www.tomgibara.com/android/veecheck/
- *
+ *
* @author jsharkey
*/
public final class UpdateHelper implements Runnable {
-
+
public final static String TAG = UpdateHelper.class.toString();
public final static String UPDATE_URL = "http://connectbot.org/version";
protected Context context;
-
+
private String packageName, versionName;
protected int versionCode;
-
+
private String userAgent;
/**
@@ -94,25 +94,25 @@ public final class UpdateHelper implements Runnable {
} catch(Exception e) {
Log.e(TAG, "Couldn't find package information in PackageManager", e);
return;
-
+
}
-
+
// decide if we really need to check for update
Resources res = context.getResources();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
-
+
String frequency = prefs.getString(res.getString(R.string.pref_update), res.getString(R.string.list_update_daily));
long lastChecked = prefs.getLong(res.getString(R.string.pref_lastchecked), 0);
long now = (System.currentTimeMillis() / 1000);
long passed = now - lastChecked;
-
+
boolean shouldCheck = false;
if(frequency.equals(res.getString(R.string.list_update_daily))) {
shouldCheck = (passed > 60 * 60 * 24);
} else if(frequency.equals(res.getString(R.string.list_update_weekly))) {
shouldCheck = (passed > 60 * 60 * 24 * 7);
}
-
+
// place version information in user-agent string to be used later
this.userAgent = String.format("%s/%s (%d, freq=%s)", packageName, versionName, versionCode, frequency);
@@ -120,12 +120,12 @@ public final class UpdateHelper implements Runnable {
// spawn thread to check for update
// Note that this class should be marked final because a thread is started in the constructor.
new Thread(this).start();
-
+
// update our last-checked time
Editor editor = prefs.edit();
editor.putLong(res.getString(R.string.pref_lastchecked), now);
editor.commit();
-
+
}
}
@@ -136,13 +136,13 @@ public final class UpdateHelper implements Runnable {
// pass information off to handler to create
JSONObject json = new JSONObject(UpdateHelper.getUrl(UPDATE_URL, userAgent));
Message.obtain(versionHandler, -1, json).sendToTarget();
-
+
} catch(Exception e) {
Log.e(TAG, "Problem while fetching/parsing update response", e);
}
}
-
+
/**
* Handler that will parse the JSON response and show dialog to user if an
@@ -160,24 +160,24 @@ public final class UpdateHelper implements Runnable {
final int versionCode = json.optInt("versionCode");
final String features = json.optString("features");
final String target = "market://" + json.optString("target");
-
+
// skip if we're already good enough
if(versionCode <= UpdateHelper.this.versionCode) return;
-
+
// build dialog to prompt user about updating
new AlertDialog.Builder(context)
.setTitle(R.string.upgrade)
.setMessage(features)
.setPositiveButton(R.string.upgrade_pos, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
+ public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(target));
context.startActivity(intent);
- }
- })
- .setNegativeButton(R.string.upgrade_neg, null).create().show();
-
+ }
+ })
+ .setNegativeButton(R.string.upgrade_neg, null).create().show();
+
}
-
+
};
@@ -186,17 +186,17 @@ public final class UpdateHelper implements Runnable {
* downtime with a 6-second timeout.
*/
private static String getUrl(String tryUrl, String userAgent) throws Exception {
-
+
URL url = new URL(tryUrl);
URLConnection connection = url.openConnection();
connection.setConnectTimeout(6000);
connection.setReadTimeout(6000);
connection.setRequestProperty("User-Agent", userAgent);
connection.connect();
-
+
InputStream is = connection.getInputStream();
ByteArrayOutputStream os = new ByteArrayOutputStream();
-
+
int bytesRead;
byte[] buffer = new byte[1024];
while ((bytesRead = is.read(buffer)) != -1) {
@@ -208,8 +208,8 @@ public final class UpdateHelper implements Runnable {
is.close();
return new String(os.toByteArray());
-
+
}
-
+
}
diff --git a/src/org/connectbot/util/XmlBuilder.java b/src/org/connectbot/util/XmlBuilder.java
index d2c2923..828d032 100644
--- a/src/org/connectbot/util/XmlBuilder.java
+++ b/src/org/connectbot/util/XmlBuilder.java
@@ -1,17 +1,17 @@
/*
ConnectBot: simple, powerful, open-source SSH client for Android
Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -25,31 +25,31 @@ import com.trilead.ssh2.crypto.Base64;
*/
public class XmlBuilder {
private StringBuilder sb;
-
+
public XmlBuilder() {
sb = new StringBuilder();
}
-
+
public XmlBuilder append(String data) {
sb.append(data);
-
+
return this;
}
-
+
public XmlBuilder append(String field, Object data) {
if (data == null) {
sb.append(String.format("<%s/>", field));
} else if (data instanceof String) {
String input = (String) data;
boolean binary = false;
-
+
for (byte b : input.getBytes()) {
if (b < 0x20 || b > 0x7e) {
binary = true;
break;
}
}
-
+
sb.append(String.format("<%s>%s</%s>", field,
binary ? new String(Base64.encode(input.getBytes())) : input, field));
} else if (data instanceof Integer) {
@@ -61,10 +61,10 @@ public class XmlBuilder {
} else if (data instanceof Boolean) {
sb.append(String.format("<%s>%s</%s>", field, (Boolean) data, field));
}
-
+
return this;
}
-
+
public String toString() {
return sb.toString();
}