diff --git a/README.md b/README.md
index 88b0891..16185a3 100644
--- a/README.md
+++ b/README.md
@@ -6,57 +6,13 @@ SSH and SFTP client library for React Native.
```
npm install react-native-ssh-sftp --save
-react-native link react-native-ssh-sftp
```
-### iOS (only)
-
-NMSSH is required for iOS.
-
-1. Initialize Pod:
- ```
- cd ios
- pod init
- ```
-2. Open Podfile and add:
- ```
- target '[your project's name]' do
- pod 'NMSSH', '2.2.8'
- end
- ```
-3. Install Pod:
- ```
- pod install
- ```
-
-### Manual Link
-
-#### iOS
-
-1. In XCode, in the project navigator, right click `Libraries` ➜ `Add Files to [your project's name]`
-2. Go to `node_modules` ➜ `react-native-ssh-sftp` and add `RNSSHClient.xcodeproj`
-3. In XCode, in the project navigator, select your project. Add `libRNSSHClient.a` to your project's `Build Phases` ➜ `Link Binary With Libraries`
-
-#### Android
-
-1. Open up `android/app/src/main/java/[...]/MainActivity.java`
- - Add `import com.reactlibrary.RNSshClientPackage;` to the imports at the top of the file
- - Add `new RNSshClientPackage()` to the list returned by the `getPackages()` method
-2. Append the following lines to `android/settings.gradle`:
- ```
- include ':react-native-ssh-sftp'
- project(':react-native-ssh-sftp').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-ssh-sftp/android')
- ```
-3. Insert the following lines inside the dependencies block in `android/app/build.gradle`:
- ```
- compile project(':react-native-ssh-sftp')
- ```
-
## Demo

-- This library is also used in iOS app PiHelper.
+- This library is also used in iOS app PiHelper.
@@ -66,6 +22,7 @@ NMSSH is required for iOS.
## Run demo
### iOS
+
```
cd example
cd ios
@@ -76,6 +33,7 @@ react-native run-ios
```
### Android
+
```
cd example
npm install
@@ -85,26 +43,33 @@ react-native run-android
## Usage
### Create a client using password authentication
+
```javascript
-import SSHClient from 'react-native-ssh-sftp';
+import SSHClient from "react-native-ssh-sftp";
-let client = new SSHClient('10.0.0.10', 22, 'user', 'password', (error) => {
- if (error)
- console.warn(error);
+let client = new SSHClient("10.0.0.10", 22, "user", "password", (error) => {
+ if (error) console.warn(error);
});
```
### Create a client using public key authentication
+
```javascript
-import SSHClient from 'react-native-ssh-sftp';
+import SSHClient from "react-native-ssh-sftp";
-let client = new SSHClient('10.0.0.10', 22, 'user', {privateKey: '-----BEGIN RSA......'}, (error) => {
- if (error)
- console.warn(error);
-});
+let client = new SSHClient(
+ "10.0.0.10",
+ 22,
+ "user",
+ { privateKey: "-----BEGIN RSA......" },
+ (error) => {
+ if (error) console.warn(error);
+ }
+);
```
- Public key authentication also supports:
+
```
{privateKey: '-----BEGIN RSA......'}
{privateKey: '-----BEGIN RSA......', publicKey: 'ssh-rsa AAAAB3NzaC1yc2EA......'}
@@ -112,51 +77,53 @@ let client = new SSHClient('10.0.0.10', 22, 'user', {privateKey: '-----BEGIN RSA
```
### Close client
+
```javascript
client.disconnect();
```
### Execute SSH command
+
```javascript
-var command = 'ls -l';
+var command = "ls -l";
client.execute(command, (error, output) => {
- if (error)
- console.warn(error);
- if (output)
- console.warn(output);
+ if (error) console.warn(error);
+ if (output) console.warn(output);
});
```
### Shell
-#### Start shell:
+#### Start shell:
+
- Supported ptyType: vanilla, vt100, vt102, vt220, ansi, xterm
+
```javascript
-var ptyType = 'vanilla';
+var ptyType = "vanilla";
client.startShell(ptyType, (error) => {
- if (error)
- console.warn(error);
+ if (error) console.warn(error);
});
```
#### Read from shell:
+
```javascript
-client.on('Shell', (event) => {
- if (event)
- console.warn(event);
+client.on("Shell", (event) => {
+ if (event) console.warn(event);
});
```
-#### Write to shell:
+#### Write to shell:
+
```javascript
-var str = 'ls -l\n';
+var str = "ls -l\n";
client.writeToShell(str, (error) => {
- if (error)
- console.warn(error);
+ if (error) console.warn(error);
});
```
-#### Close shell:
+#### Close shell:
+
```javascript
client.closeShell();
```
@@ -164,67 +131,69 @@ client.closeShell();
### SFTP
#### Connect SFTP
+
```javascript
client.connectSFTP((error) => {
- if (error)
- console.warn(error);
+ if (error) console.warn(error);
});
```
-#### List directory:
+#### List directory:
+
```javascript
-var path = '.';
+var path = ".";
client.sftpLs(path, (error, response) => {
- if (error)
- console.warn(error);
- if (response)
- console.warn(response);
+ if (error) console.warn(error);
+ if (response) console.warn(response);
});
```
-#### Create directory:
+#### Create directory:
+
```javascript
-client.sftpMkdir('dirName', (error) => {
- if (error)
- console.warn(error);
+client.sftpMkdir("dirName", (error) => {
+ if (error) console.warn(error);
});
```
-#### Rename file or directory:
+#### Rename file or directory:
+
```javascript
-client.sftpRename('oldName', 'newName', (error) => {
- if (error)
- console.warn(error);
+client.sftpRename("oldName", "newName", (error) => {
+ if (error) console.warn(error);
});
```
-#### Remove directory:
+#### Remove directory:
+
```javascript
-client.sftpRmdir('dirName', (error) => {
- if (error)
- console.warn(error);
+client.sftpRmdir("dirName", (error) => {
+ if (error) console.warn(error);
});
```
-#### Remove file:
+#### Remove file:
+
```javascript
-client.sftpRm('fileName', (error) => {
- if (error)
- console.warn(error);
+client.sftpRm("fileName", (error) => {
+ if (error) console.warn(error);
});
```
-#### Download file:
+#### Download file:
+
```javascript
-client.sftpDownload('[path-to-remote-file]', '[path-to-local-direcotry]', (error, downloadedFilePath) => {
- if (error)
- console.warn(error);
- if (downloadedFilePath)
- console.warn(downloadedFilePath);
-});
+client.sftpDownload(
+ "[path-to-remote-file]",
+ "[path-to-local-direcotry]",
+ (error, downloadedFilePath) => {
+ if (error) console.warn(error);
+ if (downloadedFilePath) console.warn(downloadedFilePath);
+ }
+);
// Downlowd progress
-client.on('DownloadProgress', (event) => {
+client.on("DownloadProgress", (event) => {
console.warn(event);
});
@@ -232,15 +201,15 @@ client.on('DownloadProgress', (event) => {
client.sftpCancelDownload();
```
-#### Upload file:
+#### Upload file:
+
```javascript
-client.sftpUpload('[path-to-local-file]', '[path-to-remote-directory]', (error) => {
- if (error)
- console.warn(error);
+client.sftpUpload("[path-to-local-file]", "[path-to-remote-directory]", (error) => {
+ if (error) console.warn(error);
});
// Upload progress
-client.on('UploadProgress', (event) => {
+client.on("UploadProgress", (event) => {
console.warn(event);
});
@@ -248,12 +217,13 @@ client.on('UploadProgress', (event) => {
client.sftpCancelUpload();
```
-#### Close SFTP:
+#### Close SFTP (Android only):
+
```javascript
client.disconnectSFTP();
```
## Credits
-* iOS SSH library: [NMSSH](https://github.com/NMSSH/NMSSH)
-* Android SSH library: [JSch](http://www.jcraft.com/jsch/)
+- iOS SSH library: [NMSSH](https://github.com/NMSSH/NMSSH)
+- Android SSH library: [JSch](http://www.jcraft.com/jsch/)
diff --git a/RNSSHClient.podspec b/RNSSHClient.podspec
index a2962e1..35a6a15 100644
--- a/RNSSHClient.podspec
+++ b/RNSSHClient.podspec
@@ -12,8 +12,8 @@ Pod::Spec.new do |s|
s.source = { :git => 'https://github.com/shaqian/react-native-ssh-sftp.git', :tag => s.version }
s.source_files = 'ios/**/*.{h,m}'
s.requires_arc = true
- s.platforms = { :ios => "8.0", :tvos => "9.2" }
+ s.platforms = { :ios => "11.0", :tvos => "9.2" }
s.dependency 'React'
- s.dependency 'NMSSH'
+ s.dependency 'NMSSH', '2.3.1'
end
diff --git a/android/build.gradle b/android/build.gradle
index cd4d6cd..7aa5d78 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -2,22 +2,27 @@
buildscript {
repositories {
jcenter()
+ google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:1.3.1'
+ classpath 'com.android.tools.build:gradle:3.2.1'
}
}
apply plugin: 'com.android.library'
+def DEFAULT_COMPILE_SDK_VERSION = 23
+def DEFAULT_BUILD_TOOLS_VERSION = "23.0.1"
+def DEFAULT_TARGET_SDK_VERSION = 22
+
android {
- compileSdkVersion 23
- buildToolsVersion "23.0.1"
+ compileSdkVersion rootProject.hasProperty('compileSdkVersion') ? rootProject.compileSdkVersion : DEFAULT_COMPILE_SDK_VERSION
+ buildToolsVersion rootProject.hasProperty('buildToolsVersion') ? rootProject.buildToolsVersion : DEFAULT_BUILD_TOOLS_VERSION
defaultConfig {
minSdkVersion 16
- targetSdkVersion 22
+ targetSdkVersion rootProject.hasProperty('targetSdkVersion') ? rootProject.targetSdkVersion : DEFAULT_TARGET_SDK_VERSION
versionCode 1
versionName "1.0"
}
@@ -28,12 +33,13 @@ android {
repositories {
mavenCentral()
+ jcenter()
}
dependencies {
- compile 'com.facebook.react:react-native:+'
- compile 'com.jcraft:jsch:0.1.54'
- compile 'com.fasterxml.jackson.core:jackson-core:2.9.0'
- compile 'com.fasterxml.jackson.core:jackson-databind:2.9.0'
+ api 'com.facebook.react:react-native:+'
+ api 'com.jcraft:jsch:0.1.54'
+ api 'com.fasterxml.jackson.core:jackson-core:2.9.0'
+ api 'com.fasterxml.jackson.core:jackson-databind:2.9.0'
}
\ No newline at end of file
diff --git a/android/src/main/java/com/reactlibrary/RNSshClientModule.java b/android/src/main/java/com/reactlibrary/RNSshClientModule.java
index a8d97ac..3fae2b1 100644
--- a/android/src/main/java/com/reactlibrary/RNSshClientModule.java
+++ b/android/src/main/java/com/reactlibrary/RNSshClientModule.java
@@ -2,7 +2,7 @@
import android.os.Environment;
import android.util.Log;
-import android.support.annotation.Nullable;
+import androidx.annotation.Nullable;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback;
diff --git a/index.d.ts b/index.d.ts
new file mode 100644
index 0000000..3ac405d
--- /dev/null
+++ b/index.d.ts
@@ -0,0 +1,35 @@
+declare module "react-native-ssh-sftp" {
+ type Callback = (error: string | any, output?: string) => void;
+ export type Handler = (output: string) => void;
+ export type PtyType = "vanilla" | "vt100" | "vt102" | "vt220" | "ansi" | "xterm";
+ export type Event = "Shell";
+ class SSHClient {
+ constructor(
+ address: string,
+ port: number,
+ username: string,
+ credential: string | { privateKey?: string; publicKey?: string; passphrase?: string },
+ callback?: Callback
+ );
+ startShell: (ptyType: PtyType, callback: Callback) => void;
+ writeToShell: (command: string, callback: Callback) => void;
+ on: (event: Event, handler: Handler) => void;
+ closeShell: () => void;
+ connect: (callback: Callback) => void;
+ connectSFTP: (callback: Callback) => void;
+ sftpLs: (path: string, callback: Callback) => void;
+ sftpRename: (oldPath: string, newPath: string, callback: Callback) => void;
+ sftpMkdir: (path: string, callback: Callback) => void;
+ sftpRm: (path: string, callback: Callback) => void;
+ sftpRmdir: (path: string, callback: Callback) => void;
+ sftpUpload: (filePath: string, path: string, callback: Callback) => void;
+ sftpCancelUpload: () => void;
+ sftpDownload: (path: string, toPath: string, callback: Callback) => void;
+ sftpCancelDownload: () => void;
+ disconnectSFTP: () => void;
+ disconnect: () => void;
+ execute: (command: string, callback: Callback) => void;
+ }
+
+ export default SSHClient;
+}
diff --git a/index.js b/index.js
index 73dc2c8..e4ce11f 100644
--- a/index.js
+++ b/index.js
@@ -1,9 +1,4 @@
-import {
- Platform,
- NativeModules,
- NativeEventEmitter,
- DeviceEventEmitter
-} from 'react-native';
+import { Platform, NativeModules, NativeEventEmitter, DeviceEventEmitter } from "react-native";
const { RNSSHClient } = NativeModules;
@@ -11,17 +6,19 @@ const RNSSHClientEmitter = new NativeEventEmitter(RNSSHClient);
class SSHClient {
// passwordOrKey: password or {privateKey: value, [publicKey: value, passphrase: value]}
- constructor(host, port, username, passwordOrKey, callback) {
- this._key = Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
+ constructor(host, port, username, passwordOrKey, callback) {
+ this._key = Math.floor((1 + Math.random()) * 0x10000)
+ .toString(16)
+ .substring(1);
this.handlers = {};
this.host = host;
this.port = port;
this.username = username;
this.passwordOrKey = passwordOrKey;
this.connect(callback);
- }
+ }
- _handleEvent (event) {
+ _handleEvent(event) {
if (this.handlers.hasOwnProperty(event.name) && this._key === event.key) {
this.handlers[event.name](event.value);
}
@@ -34,20 +31,38 @@ class SSHClient {
connect(callback) {
if (Platform.OS === "android") {
if (typeof this.passwordOrKey === "string")
- RNSSHClient.connectToHostByPassword(this.host, this.port, this.username, this.passwordOrKey, this._key,
+ RNSSHClient.connectToHostByPassword(
+ this.host,
+ this.port,
+ this.username,
+ this.passwordOrKey,
+ this._key,
(error) => {
callback && callback(error);
- });
+ }
+ );
else
- RNSSHClient.connectToHostByKey(this.host, this.port, this.username, this.passwordOrKey, this._key,
+ RNSSHClient.connectToHostByKey(
+ this.host,
+ this.port,
+ this.username,
+ this.passwordOrKey,
+ this._key,
(error) => {
callback && callback(error);
- });
+ }
+ );
} else {
- RNSSHClient.connectToHost(this.host, this.port, this.username, this.passwordOrKey, this._key,
+ RNSSHClient.connectToHost(
+ this.host,
+ this.port,
+ this.username,
+ this.passwordOrKey,
+ this._key,
(error) => {
callback && callback(error);
- });
+ }
+ );
}
}
@@ -58,11 +73,11 @@ class SSHClient {
}
// ptyType: vanilla, vt100, vt102, vt220, ansi, xterm
- startShell(ptyType, callback) {
- if (Platform.OS === 'ios') {
- this.shellListener = RNSSHClientEmitter.addListener('Shell', this._handleEvent.bind(this));
+ startShell(ptyType, callback) {
+ if (Platform.OS === "ios") {
+ this.shellListener = RNSSHClientEmitter.addListener("Shell", this._handleEvent.bind(this));
} else {
- this.shellListener = DeviceEventEmitter.addListener('Shell', this._handleEvent.bind(this));
+ this.shellListener = DeviceEventEmitter.addListener("Shell", this._handleEvent.bind(this));
}
RNSSHClient.startShell(this._key, ptyType, (error, response) => {
callback && callback(error, response);
@@ -86,12 +101,24 @@ class SSHClient {
connectSFTP(callback) {
RNSSHClient.connectSFTP(this._key, (error) => {
callback && callback(error);
- if (Platform.OS === 'ios') {
- this.downloadProgressListener = RNSSHClientEmitter.addListener('DownloadProgress', this._handleEvent.bind(this));
- this.uploadProgressListener = RNSSHClientEmitter.addListener('UploadProgress', this._handleEvent.bind(this));
+ if (Platform.OS === "ios") {
+ this.downloadProgressListener = RNSSHClientEmitter.addListener(
+ "DownloadProgress",
+ this._handleEvent.bind(this)
+ );
+ this.uploadProgressListener = RNSSHClientEmitter.addListener(
+ "UploadProgress",
+ this._handleEvent.bind(this)
+ );
} else {
- this.downloadProgressListener = DeviceEventEmitter.addListener('DownloadProgress', this._handleEvent.bind(this));
- this.uploadProgressListener = DeviceEventEmitter.addListener('UploadProgress', this._handleEvent.bind(this));
+ this.downloadProgressListener = DeviceEventEmitter.addListener(
+ "DownloadProgress",
+ this._handleEvent.bind(this)
+ );
+ this.uploadProgressListener = DeviceEventEmitter.addListener(
+ "UploadProgress",
+ this._handleEvent.bind(this)
+ );
}
});
}
@@ -147,24 +174,23 @@ class SSHClient {
}
disconnectSFTP() {
- if (this.downloadProgressListener) {
- this.downloadProgressListener.remove();
- this.downloadProgressListener = null;
- }
- if (this.uploadProgressListener) {
- this.uploadProgressListener.remove();
- this.uploadProgressListener = null;
+ if (Platform.OS !== "ios") {
+ if (this.downloadProgressListener) {
+ this.downloadProgressListener.remove();
+ this.downloadProgressListener = null;
+ }
+ if (this.uploadProgressListener) {
+ this.uploadProgressListener.remove();
+ this.uploadProgressListener = null;
+ }
+ RNSSHClient.disconnectSFTP(this._key);
}
- RNSSHClient.disconnectSFTP(this._key);
}
disconnect() {
- if (this.shellListener)
- this.shellListener.remove();
- if (this.downloadProgressListener)
- this.downloadProgressListener.remove();
- if (this.uploadProgressListener)
- this.uploadProgressListener.remove();
+ if (this.shellListener) this.shellListener.remove();
+ if (this.downloadProgressListener) this.downloadProgressListener.remove();
+ if (this.uploadProgressListener) this.uploadProgressListener.remove();
RNSSHClient.disconnect(this._key);
}
}
diff --git a/ios/SSHClient.m b/ios/SSHClient.m
index 1921b82..5fdd719 100644
--- a/ios/SSHClient.m
+++ b/ios/SSHClient.m
@@ -15,7 +15,7 @@ @implementation SSHClient
- (instancetype)init {
if ((self = [super init])) {
- _session = [NMSSHSession new];
+ _session = nil;
_sftpSession = [[NMSFTP alloc] init];
_key = [[NSString alloc] init];
_downloadContinue = false;
diff --git a/package.json b/package.json
index 6dccaa2..9e56c4c 100644
--- a/package.json
+++ b/package.json
@@ -18,11 +18,11 @@
"author": "Qian Sha",
"license": "MIT",
"peerDependencies": {
- "react-native": "^0.54.0"
+ "react-native": "*"
},
- "repository" :
- {
- "type" : "git",
- "url" : "https://github.com/shaqian/react-native-ssh-sftp.git"
+ "types": "./index.d.ts",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/shaqian/react-native-ssh-sftp.git"
}
}