Skip to content

Commit 6d79e55

Browse files
committed
release v2.2.2
1 parent 9ba67b6 commit 6d79e55

File tree

10 files changed

+153
-121
lines changed

10 files changed

+153
-121
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 2.2.2
2+
* Update mwiede jsch to version 0.1.66: https://github.com/mwiede/jsch/releases/tag/jsch-0.1.66
3+
* Support for several more algorithms in Android, including ssh-ed25519
4+
* Bug fixes and improvements for example app
5+
* Bump kotlin version and targetSdkVersion for Android
6+
17
## 2.2.1
28
* Fix bug in isConnected that affected sftp connections in iOS
39
* Add function to get host fingerprint

android/build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ android {
3333
}
3434

3535
dependencies {
36-
implementation 'com.github.mwiede:jsch:0.1.65'
36+
implementation 'org.bouncycastle:bcprov-jdk15on:1.69'
37+
implementation 'com.github.mwiede:jsch:0.1.66'
3738
}
3839

3940
compileOptions {

example/android/app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
2626
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
2727

2828
android {
29-
compileSdkVersion 30
29+
compileSdkVersion 31
3030

3131
sourceSets {
3232
main.java.srcDirs += 'src/main/kotlin'
@@ -36,7 +36,7 @@ android {
3636
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
3737
applicationId "com.example.example"
3838
minSdkVersion 16
39-
targetSdkVersion 30
39+
targetSdkVersion 31
4040
versionCode flutterVersionCode.toInteger()
4141
versionName flutterVersionName
4242
}

example/android/app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
android:icon="@mipmap/ic_launcher">
66
<activity
77
android:name=".MainActivity"
8+
android:exported="true"
89
android:launchMode="singleTop"
910
android:theme="@style/LaunchTheme"
1011
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"

example/android/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
buildscript {
2-
ext.kotlin_version = '1.4.20'
2+
ext.kotlin_version = '1.5.30'
33
repositories {
44
google()
55
mavenCentral()
66
}
77

88
dependencies {
9-
classpath 'com.android.tools.build:gradle:7.0.1'
9+
classpath 'com.android.tools.build:gradle:7.0.2'
1010
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
1111
}
1212
}

example/ios/Podfile.lock

Lines changed: 0 additions & 35 deletions
This file was deleted.

example/lib/main.dart

Lines changed: 131 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -16,39 +16,11 @@ class _MyAppState extends State<MyApp> {
1616
String _result = '';
1717
List _array = [];
1818

19-
final ButtonStyle buttonStyle =
20-
TextButton.styleFrom(backgroundColor: Colors.blue);
21-
22-
Future<void> onClickCmd() async {
23-
var client = new SSHClient(
24-
host: "hostname",
25-
port: 22,
26-
username: "username",
27-
passwordOrKey: "password",
28-
);
29-
30-
String result = '';
31-
try {
32-
result = (await client.connect())!;
33-
if (result == "session_connected") result = (await client.execute("ps"))!;
34-
client.disconnect();
35-
} on PlatformException catch (e) {
36-
print('Error: ${e.code}\nError Message: ${e.message}');
37-
}
38-
39-
setState(() {
40-
_result = result;
41-
_array = [];
42-
});
43-
}
44-
45-
Future<void> onClickShell() async {
46-
var client = new SSHClient(
47-
host: "hostname",
48-
port: 22,
49-
username: "username",
50-
passwordOrKey: {
51-
"privateKey": """-----BEGIN RSA PRIVATE KEY-----
19+
// ***** Change these settings for your environment *****
20+
final String hostname = 'changeme';
21+
final String username = 'changeme';
22+
final String password = 'changeme';
23+
final String privateKey = """-----BEGIN RSA PRIVATE KEY-----
5224
MIIEpAIBAAKCAQEA2DdFSeWG8wOHddRpOhf4FRqksJITr59iXdNrXq+n79QFN1g4
5325
bvRG9zCDmyLb8EF+gah78dpJsGZVIltmfYWpsk7ok9GT/foCB1d2E6DbEU6mBIPe
5426
OLxYOqyiea8mi7iGt9BvAB4Mj+v2LnhK4O2BB6PTU4KLjSgMdqtV/EGctLdK+JEU
@@ -74,96 +46,183 @@ VYm6XcNwPF/t5SM01ZuxH9NE2HZJ1cHcUGYQcUUJuqSkzsVK9j32E/akW9Cg3LVD
7446
D/fESTECgYBwWv9yveto6pP6/xbR9k/Jdgr+vXQ3BJVU3BOsD38SeSrZfMSNGqgx
7547
eiukCOIsRHYY7Qqi2vCJ62mwbHJ3RhSKKxcGpgzGX7KoGZS+bb5wb7RGNYK/mVaI
7648
pFkz72+8eA2cnbWUqHt9WqMUgUBYZTMESzQrTf7+q+0gWf49AZJ/QQ==
77-
-----END RSA PRIVATE KEY-----""",
78-
},
79-
);
49+
-----END RSA PRIVATE KEY-----""";
50+
final String passphrase = "changeme"; // For password encrypted private key
51+
52+
final ButtonStyle buttonStyle =
53+
TextButton.styleFrom(backgroundColor: Colors.blue);
8054

55+
void resetValues() {
8156
setState(() {
82-
_result = "";
57+
_result = 'Loading';
8358
_array = [];
8459
});
60+
}
61+
62+
Future<void> onClickCmd() async {
63+
String result = '';
64+
65+
resetValues();
66+
67+
var client = new SSHClient(
68+
host: hostname,
69+
port: 22,
70+
username: username,
71+
passwordOrKey: password,
72+
);
8573

8674
try {
87-
String result = (await client.connect())!;
75+
result = await client.connect() ?? 'Null result';
76+
if (result == "session_connected") result = await client.execute("ps") ?? 'Null result';
77+
await client.disconnect();
78+
} on PlatformException catch (e) {
79+
String errorMessage = 'Error: ${e.code}\nError Message: ${e.message}';
80+
result = errorMessage;
81+
print(errorMessage);
82+
}
83+
84+
setState(() {
85+
_result = result;
86+
});
87+
}
88+
89+
Future<void> onClickShell() async {
90+
String result = '';
91+
92+
resetValues();
93+
94+
var client = new SSHClient(
95+
host: hostname,
96+
port: 22,
97+
username: username,
98+
passwordOrKey: {
99+
"privateKey": privateKey,
100+
"passphrase": passphrase, // Remove line if key is not password protected
101+
},
102+
);
103+
104+
try {
105+
result = await client.connect() ?? 'Null result';
106+
88107
if (result == "session_connected") {
89-
result = (await client.startShell(
108+
result = await client.startShell(
90109
ptyType: "xterm",
91110
callback: (dynamic res) {
92111
setState(() {
93-
_result += res;
112+
result += res;
94113
});
95-
}))!;
114+
}) ?? 'Null result';
96115

97116
if (result == "shell_started") {
98117
print(await client.writeToShell("echo hello > world\n"));
99118
print(await client.writeToShell("cat world\n"));
100-
new Future.delayed(
101-
const Duration(seconds: 5),
102-
() async => await client.closeShell(),
103-
);
119+
104120
}
121+
122+
// Disconnect from SSH client
123+
await client.disconnect();
105124
}
106125
} on PlatformException catch (e) {
107-
print('Error: ${e.code}\nError Message: ${e.message}');
126+
String errorMessage = 'Error: ${e.code}\nError Message: ${e.message}';
127+
result += errorMessage;
128+
print(errorMessage);
108129
}
130+
131+
setState(() {
132+
_result = result;
133+
});
109134
}
110135

111136
Future<void> onClickSFTP() async {
137+
String result = '';
138+
List array = [];
139+
140+
resetValues();
141+
112142
var client = new SSHClient(
113-
host: "hostname",
143+
host: hostname,
114144
port: 22,
115-
username: "username",
116-
passwordOrKey: "password",
145+
username: username,
146+
passwordOrKey: password,
117147
);
118148

119149
try {
120-
String result = (await client.connect())!;
150+
result = await client.connect() ?? 'Null result';
121151
if (result == "session_connected") {
122-
result = (await client.connectSFTP())!;
152+
result = await client.connectSFTP() ?? 'Null result';
123153
if (result == "sftp_connected") {
124-
var array = await client.sftpLs();
125-
setState(() {
126-
_result = result;
127-
_array = array!;
128-
});
154+
array = await client.sftpLs() ?? [];
129155

156+
// Create a test directory
130157
print(await client.sftpMkdir("testsftp"));
158+
159+
// Rename the test directory
131160
print(await client.sftpRename(
132161
oldPath: "testsftp",
133162
newPath: "testsftprename",
134163
));
164+
165+
// Remove the renamed test directory
135166
print(await client.sftpRmdir("testsftprename"));
136167

168+
// Get local device temp directory
137169
Directory tempDir = await getTemporaryDirectory();
138170
String tempPath = tempDir.path;
139-
var filePath = await client.sftpDownload(
140-
path: "testupload",
141-
toPath: tempPath,
142-
callback: (progress) async {
143-
print(progress);
144-
// if (progress == 20) await client.sftpCancelDownload();
145-
},
146-
);
147171

148-
print(await client.sftpRm("testupload"));
172+
// Create local test file
173+
final String fileName = 'ssh2_test_upload.txt';
174+
final File file = File('$tempPath/$fileName');
175+
await file.writeAsString('Testing file upload');
149176

177+
print('Local file path is ${file.path}');
178+
179+
// Upload test file
150180
print(await client.sftpUpload(
151-
path: (filePath)!,
181+
path: file.path,
152182
toPath: ".",
153183
callback: (progress) async {
154184
print(progress);
155185
// if (progress == 30) await client.sftpCancelUpload();
156186
},
157-
));
187+
) ?? 'Upload failed');
188+
189+
// Download test file
190+
print(await client.sftpDownload(
191+
path: fileName,
192+
toPath: tempPath,
193+
callback: (progress) async {
194+
print(progress);
195+
// if (progress == 20) await client.sftpCancelDownload();
196+
},
197+
) ?? 'Download failed');
158198

159-
print(await client.disconnectSFTP());
199+
// Delete the remote test file
200+
print(await client.sftpRm(fileName));
160201

161-
client.disconnect();
202+
// Delete the local test file
203+
await file.delete();
204+
205+
// Disconnect from SFTP client - don't use
206+
// There is a bug that prevents the ssh client connection from being
207+
// closed after calling disconnectSFTP()
208+
//print(await client.disconnectSFTP());
209+
210+
// Disconnect from SSH client
211+
await client.disconnect();
162212
}
213+
214+
163215
}
164216
} on PlatformException catch (e) {
165-
print('Error: ${e.code}\nError Message: ${e.message}');
217+
String errorMessage = 'Error: ${e.code}\nError Message: ${e.message}';
218+
result += errorMessage;
219+
print(errorMessage);
166220
}
221+
222+
setState(() {
223+
_result = result;
224+
_array = array;
225+
});
167226
}
168227

169228
@override
@@ -205,14 +264,14 @@ pFkz72+8eA2cnbWUqHt9WqMUgUBYZTMESzQrTf7+q+0gWf49AZJ/QQ==
205264
return MaterialApp(
206265
home: Scaffold(
207266
appBar: AppBar(
208-
title: const Text('ssh plugin example app'),
267+
title: const Text('ssh2 plugin example app'),
209268
),
210269
body: ListView(
211270
shrinkWrap: true,
212271
padding: EdgeInsets.all(15.0),
213272
children: <Widget>[
214273
Text(
215-
"Please edit the connection setting in the source code before clicking the test buttons"),
274+
"Please edit the connection settings in the source code before clicking the test buttons"),
216275
renderButtons(),
217276
Text(_result),
218277
_array.length > 0

0 commit comments

Comments
 (0)