Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Latest commit

 

History

History
History
315 lines (285 loc) · 13.1 KB

File metadata and controls

315 lines (285 loc) · 13.1 KB
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
package com.example.git;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Environment;
import android.text.InputType;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.KeyPair;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* This activity handles the settings of the application.
* These settings are:
* - a private SSH key
* - a public SSH key
* It is possible to generate a new SSH key pair or use some different keys, by selecting there location.
*/
public class SettingsActivity extends Activity {
/**
* The tag is used to identify the class while logging.
*/
private final String TAG = getClass().getName();
/**
* The path to the private key.
*/
private String sshPrivateKeyPath = "";
/**
* The path to the public key.
*/
private String sshPublicKeyPath = "";
/**
* The current context within the application.
*/
private final Context currentContext = SettingsActivity.this;
/**
* The absolute path to the default folder where the SSH keys are stored.
*/
private final static String defaultAbsoluteKeyPath = Environment.getExternalStorageDirectory() + "/.ssh/";
/**
* The name of the default private key.
*/
private final static String defaultPrivateKeyName = "id_rsa";
/**
* The name of the default public key.
*/
private final static String defaultPublicKeyName = "id_rsa.pub";
/**
* Constant to identify the origin of the request.
*/
private static final int PICKPRIVATEKEYPATHREQUEST = 0;
/**
* Constant to identify the origin of the request.
*/
private static final int PICKPUBLICKEYPATHREQUEST = 1;
@Override
/**
* Called when the activity is starting. Applies actions to each element of the layout.
* @param savedInstanceState If the activity is being re-initialized after previously being shut down then this Bundle contains the data it most recently supplied in onSaveInstanceState(Bundle). Note: Otherwise it is null.
*/
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
SharedPreferences settings = getSharedPreferences(currentContext.getResources().getString(R.string.APPSETTINGS), 0);
sshPrivateKeyPath = settings.getString(currentContext.getResources().getString(R.string.SSHPRIVATEKEYPATHSETTING), "");
sshPublicKeyPath = settings.getString(currentContext.getResources().getString(R.string.SSHPUBLICKEYPATHSETTING), "");
final EditText sshPrivateKeyPathEditText = (EditText) findViewById(R.id.ssh_private_key_path);
if (!"".equals(sshPrivateKeyPath)) {
sshPrivateKeyPathEditText.setText(sshPrivateKeyPath);
}
sshPrivateKeyPathEditText.setEnabled(false);
Button sshPrivateKeyPathButton = (Button) findViewById(R.id.button_select_folder_ssh_private_key_path);
sshPrivateKeyPathButton.setOnClickListener(new View.OnClickListener() {
/**
* Called when the sshPrivateKeyPathButton button has been clicked.
* Starts the FileBrowserActivity, so the user can select the path to the SSH private key.
* @param view The view that was clicked.
*/
public void onClick(View view) {
Intent intent = new Intent(currentContext, FileBrowserActivity.class);
intent.putExtra(FileBrowserActivity.SELECTIONTYPE, Integer.toString(FileBrowserActivity.SELECTIONTYPE_FILE));
startActivityForResult(intent, PICKPRIVATEKEYPATHREQUEST);
}
});
final EditText sshPublicKeyPathEditText = (EditText) findViewById(R.id.ssh_public_key_path);
if (!"".equals(sshPublicKeyPath)) {
sshPublicKeyPathEditText.setText(sshPublicKeyPath);
}
sshPublicKeyPathEditText.setEnabled(false);
Button sshPublicKeyPathButton = (Button) findViewById(R.id.button_select_folder_ssh_public_key_path);
sshPublicKeyPathButton.setOnClickListener(new View.OnClickListener() {
/**
* Called when the sshPublicKeyPathButton button has been clicked.
* Starts the FileBrowserActivity, so the user can select the path to the SSH public key.
* @param view The view that was clicked.
*/
public void onClick(View view) {
Intent intent = new Intent(currentContext, FileBrowserActivity.class);
intent.putExtra(FileBrowserActivity.SELECTIONTYPE, Integer.toString(FileBrowserActivity.SELECTIONTYPE_FILE));
startActivityForResult(intent, PICKPUBLICKEYPATHREQUEST);
}
});
Button generateKeyPairButton = (Button) findViewById(R.id.button_genKeys);
generateKeyPairButton.setOnClickListener(new View.OnClickListener() {
/**
* Called when the generateKeyPairButton button has been clicked.
* Generates a SSH key pair and saves them to the filesystem.
* @param view The view that was clicked.
*/
public void onClick(View view) {
buttonKeyPairGenerationAction(sshPrivateKeyPathEditText, sshPublicKeyPathEditText);
}
});
Button saveSettingsButton = (Button) findViewById(R.id.button_save);
saveSettingsButton.setOnClickListener(new View.OnClickListener() {
/**
* Called when the saveSettingsButton button has been clicked.
* Saves the settings for the SSH key pair.
* @param view The view that was clicked.
*/
public void onClick(View view) {
saveSetting(currentContext.getResources().getString(R.string.SSHPRIVATEKEYPATHSETTING), sshPrivateKeyPath);
saveSetting(currentContext.getResources().getString(R.string.SSHPUBLICKEYPATHSETTING), sshPublicKeyPath);
finish();
}
});
}
/**
* Checks if a private named id.rsa and public key named id_pub.rsa are already available at the default location .ssh in the external media.
*/
private boolean defaultKeyPairAvailable() {
boolean keyPairAvailable = false;
if (defaultPrivateKeyName != null && defaultPublicKeyName != null) {
File privateKey = new File(defaultAbsoluteKeyPath, defaultPrivateKeyName);
File publicKey = new File(defaultAbsoluteKeyPath, defaultPublicKeyName);
keyPairAvailable = (privateKey.exists() && publicKey.exists());
}
return keyPairAvailable;
}
/**
* Executes the actions to generate the SSH key pair and requests the required user input.
* @param sshPrivateKeyPathEditText The view that shows the path to the private key.
* @param sshPublicKeyPathEditText The view that shows the path to the public key.
*/
private void buttonKeyPairGenerationAction(final EditText sshPrivateKeyPathEditText, final EditText sshPublicKeyPathEditText) {
if (!defaultKeyPairAvailable()) {
AlertDialog.Builder alert = new AlertDialog.Builder(currentContext);
alert.setTitle(currentContext.getResources().getString(R.string.enter_password) + currentContext.getResources().getString(R.string.optional));
alert.setMessage(currentContext.getResources().getString(R.string.password));
final EditText input = new EditText(currentContext);
input.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
alert.setView(input);
alert.setPositiveButton(currentContext.getResources().getString(R.string.ok), new DialogInterface.OnClickListener() {
/**
* This method will be invoked when the PositiveButton button in the dialog is clicked.
* It launches the action to generate a new SSH key pair.
* @param dialog The dialog that received the click.
* @param which The button that was clicked.
*/
public void onClick(DialogInterface dialog, int whichButton) {
if (generateKeyPair(KeyPair.RSA, defaultAbsoluteKeyPath, defaultPrivateKeyName, defaultPublicKeyName, "", input.getText().toString())) {
sshPrivateKeyPathEditText.setText(defaultAbsoluteKeyPath + defaultPrivateKeyName);
sshPublicKeyPathEditText.setText(defaultAbsoluteKeyPath + defaultPublicKeyName);
sshPrivateKeyPath = defaultAbsoluteKeyPath + defaultPrivateKeyName;
sshPublicKeyPath = defaultAbsoluteKeyPath + defaultPublicKeyName;
ToastNotification.makeToast(currentContext.getResources().getString(R.string.keypair_location) + defaultAbsoluteKeyPath, Toast.LENGTH_LONG, currentContext);
} else {
ToastNotification.makeToast(currentContext.getResources().getString(R.string.keypair_generation_failed), Toast.LENGTH_LONG, currentContext);
}
}
});
alert.setNegativeButton(currentContext.getResources().getString(R.string.cancel), new DialogInterface.OnClickListener() {
/**
* This method will be invoked when the NegativeButton button in the dialog is clicked.
* It does nothing except a return to cancel the dialog.
* @param dialog The dialog that received the click.
* @param which The button that was clicked.
*/
public void onClick(DialogInterface dialog, int which) {
return;
}
});
alert.show();
}
else {
ToastNotification.makeToast(currentContext.getResources().getString(R.string.keypair_exists), Toast.LENGTH_LONG, currentContext);
}
}
/**
* Save a setting for the application.
* @param key The key of the setting.
* @param value The value of the setting.
*/
private void saveSetting(String key, String value) {
SharedPreferences settings = getSharedPreferences(currentContext.getResources().getString(R.string.APPSETTINGS), 0);
SharedPreferences.Editor editor = settings.edit();
editor.putString(key, value);
editor.commit();
}
/**
* Called when the FileBrowserActivity which was launched in onCreate() via the pathButtons exits, gives the requestCode you started it with,
* the resultCode it returned, and any additional data from it.
* @param requestCode The integer request code originally supplied to startActivityForResult(), allows to identify who this result came from.
* @param resultCode The integer result code returned by the child activity through its setResult().
* @param data An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
*/
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PICKPUBLICKEYPATHREQUEST) {
if (resultCode == RESULT_OK) {
sshPublicKeyPath = data.getStringExtra(FileBrowserActivity.SELECTION);
EditText sshPublicKeyPathEditText = (EditText) findViewById(R.id.ssh_public_key_path);
sshPublicKeyPathEditText.setText(sshPublicKeyPath);
sshPublicKeyPathEditText.setEnabled(false);
}
if (resultCode == RESULT_CANCELED) {
ToastNotification.makeToast(currentContext.getResources().getString(R.string.filebrowser_nothing_selected), Toast.LENGTH_LONG, currentContext);
}
}
if (requestCode == PICKPRIVATEKEYPATHREQUEST) {
if (resultCode == RESULT_OK) {
sshPrivateKeyPath = data.getStringExtra(FileBrowserActivity.SELECTION);
EditText sshPrivateKeyPathEditText = (EditText) findViewById(R.id.ssh_private_key_path);
sshPrivateKeyPathEditText.setText(sshPrivateKeyPath);
sshPrivateKeyPathEditText.setEnabled(false);
}
if (resultCode == RESULT_CANCELED) {
ToastNotification.makeToast(currentContext.getResources().getString(R.string.filebrowser_nothing_selected), Toast.LENGTH_LONG, currentContext);
}
}
}
/**
* Generates a public and a private key, which can be used for SSH.
* @param keyType The type of the keys DSA or RSA, 1 for DSA, 2 for RSA
* @param absoluteKeyPath The path where the keys should be stored.
* @param privateKeyFilename The filename of the private key.
* @param publicKeyFilename The filename of the public key.
* @param comment The comment thats included in the public key file.
* @param password The password that will be used for the private key, can be an empty String.
*/
private boolean generateKeyPair(Integer keyType, String absoluteKeyPath, String privateKeyFilename, String publicKeyFilename, String comment, String password) {
boolean success = false;
File folder = new File(absoluteKeyPath);
if (!folder.exists()) {
folder.mkdir();
}
if (folder.exists()) {
if (keyType == KeyPair.DSA || keyType == KeyPair.RSA) {
JSch jsch = new JSch();
KeyPair kpair;
try {
kpair = KeyPair.genKeyPair(jsch, keyType);
kpair.setPassphrase(password);
kpair.writePrivateKey(absoluteKeyPath + privateKeyFilename);
kpair.writePublicKey(absoluteKeyPath + publicKeyFilename, comment);
kpair.dispose();
success = true;
} catch (JSchException exception) {
Log.e(TAG, currentContext.getResources().getString(R.string.keypair_creation_failed));
exception.printStackTrace();
} catch (FileNotFoundException exception) {
Log.e(TAG, currentContext.getResources().getString(R.string.keypair_creation_failed));
exception.printStackTrace();
} catch (IOException exception) {
Log.e(TAG, currentContext.getResources().getString(R.string.keypair_creation_failed));
exception.printStackTrace();
}
} else {
Log.e(TAG, currentContext.getResources().getString(R.string.invalid_ssh_keytype));
}
} else {
Log.e(TAG, currentContext.getResources().getString(R.string.keypair_folder_creation_failed));
}
return success;
}
}
Morty Proxy This is a proxified and sanitized view of the page, visit original site.