mirror of
https://github.com/neon443/ShhShell.git
synced 2026-03-11 05:19:13 +00:00
moved lots of logic into sshHandler
increased deployment target bc i cba rn
This commit is contained in:
@@ -555,7 +555,7 @@
|
|||||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14;
|
IPHONEOS_DEPLOYMENT_TARGET = 16;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@@ -586,7 +586,7 @@
|
|||||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14;
|
IPHONEOS_DEPLOYMENT_TARGET = 16;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ class SSHHandler: ObservableObject {
|
|||||||
private var channel: ssh_channel?
|
private var channel: ssh_channel?
|
||||||
|
|
||||||
@Published var authorized: Bool = false
|
@Published var authorized: Bool = false
|
||||||
|
@Published var connected: Bool = false
|
||||||
|
@Published var testSuceeded: Bool = false
|
||||||
|
|
||||||
@Published var host: HostPr
|
@Published var host: HostPr
|
||||||
@Published var terminal: String = ""
|
@Published var terminal: String = ""
|
||||||
@@ -43,7 +45,7 @@ class SSHHandler: ObservableObject {
|
|||||||
return Data(base64Encoded: String(cString: data))
|
return Data(base64Encoded: String(cString: data))
|
||||||
}
|
}
|
||||||
|
|
||||||
func connect() -> Bool {
|
func connect() {
|
||||||
defer {
|
defer {
|
||||||
getAuthMethods()
|
getAuthMethods()
|
||||||
self.host.key = getHostkey()
|
self.host.key = getHostkey()
|
||||||
@@ -53,7 +55,8 @@ class SSHHandler: ObservableObject {
|
|||||||
|
|
||||||
session = ssh_new()
|
session = ssh_new()
|
||||||
guard session != nil else {
|
guard session != nil else {
|
||||||
return false
|
connected = false
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_options_set(session, SSH_OPTIONS_HOST, host.address)
|
ssh_options_set(session, SSH_OPTIONS_HOST, host.address)
|
||||||
@@ -64,9 +67,11 @@ class SSHHandler: ObservableObject {
|
|||||||
if status != SSH_OK {
|
if status != SSH_OK {
|
||||||
logger.critical("connection not ok: \(status)")
|
logger.critical("connection not ok: \(status)")
|
||||||
logSshGetError()
|
logSshGetError()
|
||||||
return false
|
connected = false
|
||||||
|
return
|
||||||
}
|
}
|
||||||
return true
|
connected = true
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func disconnect() {
|
func disconnect() {
|
||||||
@@ -81,26 +86,34 @@ class SSHHandler: ObservableObject {
|
|||||||
host.key = nil
|
host.key = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func testExec() -> Bool {
|
func testExec() {
|
||||||
if ssh_is_connected(session) == 0 {
|
if ssh_is_connected(session) == 0 {
|
||||||
return false
|
testSuceeded = false
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard authorized else { return false }
|
guard authorized else {
|
||||||
|
testSuceeded = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var status: CInt
|
var status: CInt
|
||||||
var buffer: [Int] = Array(repeating: 0, count: 256)
|
var buffer: [Int] = Array(repeating: 0, count: 256)
|
||||||
var nbytes: CInt
|
var nbytes: CInt
|
||||||
|
|
||||||
let channel = ssh_channel_new(session)
|
let channel = ssh_channel_new(session)
|
||||||
guard channel != nil else { return false }
|
guard channel != nil else {
|
||||||
|
testSuceeded = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
status = ssh_channel_open_session(channel)
|
status = ssh_channel_open_session(channel)
|
||||||
guard status == SSH_OK else {
|
guard status == SSH_OK else {
|
||||||
ssh_channel_free(channel)
|
ssh_channel_free(channel)
|
||||||
logger.critical("session opening error")
|
logger.critical("session opening error")
|
||||||
logSshGetError()
|
logSshGetError()
|
||||||
return false
|
testSuceeded = false
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
status = ssh_channel_request_exec(channel, "uptime")
|
status = ssh_channel_request_exec(channel, "uptime")
|
||||||
@@ -109,7 +122,8 @@ class SSHHandler: ObservableObject {
|
|||||||
ssh_channel_free(channel)
|
ssh_channel_free(channel)
|
||||||
logger.critical("session opening error")
|
logger.critical("session opening error")
|
||||||
logSshGetError()
|
logSshGetError()
|
||||||
return false
|
testSuceeded = false
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
nbytes = ssh_channel_read(
|
nbytes = ssh_channel_read(
|
||||||
@@ -125,7 +139,8 @@ class SSHHandler: ObservableObject {
|
|||||||
ssh_channel_free(channel)
|
ssh_channel_free(channel)
|
||||||
logger.critical("write error")
|
logger.critical("write error")
|
||||||
logSshGetError()
|
logSshGetError()
|
||||||
return false
|
testSuceeded = false
|
||||||
|
return
|
||||||
}
|
}
|
||||||
nbytes = ssh_channel_read(channel, &buffer, UInt32(MemoryLayout.size(ofValue: Character.self)), 0)
|
nbytes = ssh_channel_read(channel, &buffer, UInt32(MemoryLayout.size(ofValue: Character.self)), 0)
|
||||||
}
|
}
|
||||||
@@ -135,14 +150,16 @@ class SSHHandler: ObservableObject {
|
|||||||
ssh_channel_free(channel)
|
ssh_channel_free(channel)
|
||||||
logger.critical("didnt read?")
|
logger.critical("didnt read?")
|
||||||
logSshGetError()
|
logSshGetError()
|
||||||
return false
|
testSuceeded = false
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_channel_send_eof(channel)
|
ssh_channel_send_eof(channel)
|
||||||
ssh_channel_close(channel)
|
ssh_channel_close(channel)
|
||||||
ssh_channel_free(channel)
|
ssh_channel_free(channel)
|
||||||
print("testExec succeeded")
|
print("testExec succeeded")
|
||||||
return true
|
testSuceeded = true
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func authWithPubkey() -> Bool {
|
func authWithPubkey() -> Bool {
|
||||||
|
|||||||
@@ -9,79 +9,75 @@ import SwiftUI
|
|||||||
|
|
||||||
struct ContentView: View {
|
struct ContentView: View {
|
||||||
@ObservedObject var handler: SSHHandler
|
@ObservedObject var handler: SSHHandler
|
||||||
@State var connected: Bool = false
|
// @State var connected: Bool = false
|
||||||
@State var testSucceded: Bool?
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
NavigationStack {
|
||||||
Text(connected ? "connected" : "not connected")
|
List {
|
||||||
.modifier(foregroundColorStyle(connected ? .green : .red))
|
HStack {
|
||||||
|
Text(handler.connected ? "connected" : "not connected")
|
||||||
Text(handler.authorized ? "authorized" : "unauthorized")
|
.modifier(foregroundColorStyle(handler.connected ? .green : .red))
|
||||||
.modifier(foregroundColorStyle(handler.authorized ? .green : .red))
|
|
||||||
|
Text(handler.authorized ? "authorized" : "unauthorized")
|
||||||
if let testSucceded = testSucceded {
|
.modifier(foregroundColorStyle(handler.authorized ? .green : .red))
|
||||||
Image(systemName: testSucceded ? "checkmark.circle" : "xmark.circle")
|
}
|
||||||
.modifier(foregroundColorStyle(testSucceded ? .green : .red))
|
|
||||||
}
|
// if let testSucceded = testSucceded {
|
||||||
|
// Image(systemName: testSucceded ? "checkmark.circle" : "xmark.circle")
|
||||||
if handler.host.key != nil {
|
// .modifier(foregroundColorStyle(testSucceded ? .green : .red))
|
||||||
Text("Hostkey: \(handler.host.key!.base64EncodedString())")
|
// }
|
||||||
}
|
|
||||||
|
if handler.host.key != nil {
|
||||||
TextField("address", text: $handler.host.address)
|
Text("Hostkey: \(handler.host.key!.base64EncodedString())")
|
||||||
.textFieldStyle(.roundedBorder)
|
}
|
||||||
|
|
||||||
TextField(
|
TextField("address", text: $handler.host.address)
|
||||||
"port",
|
.textFieldStyle(.roundedBorder)
|
||||||
text: Binding(
|
|
||||||
get: { String(handler.host.port) },
|
TextField(
|
||||||
set: { handler.host.port = Int($0) ?? 22} )
|
"port",
|
||||||
)
|
text: Binding(
|
||||||
|
get: { String(handler.host.port) },
|
||||||
|
set: { handler.host.port = Int($0) ?? 22} )
|
||||||
|
)
|
||||||
.keyboardType(.numberPad)
|
.keyboardType(.numberPad)
|
||||||
.textFieldStyle(.roundedBorder)
|
.textFieldStyle(.roundedBorder)
|
||||||
|
|
||||||
TextField("username", text: $handler.host.username)
|
TextField("username", text: $handler.host.username)
|
||||||
.textFieldStyle(.roundedBorder)
|
.textFieldStyle(.roundedBorder)
|
||||||
|
|
||||||
TextField("password", text: $handler.host.password)
|
TextField("password", text: $handler.host.password)
|
||||||
.textFieldStyle(.roundedBorder)
|
.textFieldStyle(.roundedBorder)
|
||||||
|
|
||||||
Button("connect") {
|
Button() {
|
||||||
if handler.connect() {
|
handler.connect()
|
||||||
withAnimation { connected = true }
|
let _ = handler.authWithPw()
|
||||||
|
handler.openShell()
|
||||||
|
} label: {
|
||||||
|
Label("Connect", systemImage: "powerplug.portrait")
|
||||||
}
|
}
|
||||||
handler.authWithPw()
|
.disabled(handler.connected)
|
||||||
}
|
|
||||||
.disabled(connected)
|
NavigationLink() {
|
||||||
|
TerminalView(handler: handler)
|
||||||
Button("disconnect") {
|
} label: {
|
||||||
handler.disconnect()
|
Label("Open Terminal", systemImage: "apple.terminal")
|
||||||
withAnimation { testSucceded = false }
|
|
||||||
withAnimation { connected = false }
|
|
||||||
withAnimation { testSucceded = nil }
|
|
||||||
}
|
|
||||||
.disabled(!connected)
|
|
||||||
|
|
||||||
Button("run a test command") {
|
|
||||||
if handler.testExec() {
|
|
||||||
withAnimation { testSucceded = true }
|
|
||||||
} else {
|
|
||||||
withAnimation { testSucceded = false }
|
|
||||||
}
|
}
|
||||||
|
.disabled(!(handler.connected && handler.authorized))
|
||||||
|
|
||||||
|
Button() {
|
||||||
|
withAnimation { handler.testExec() }
|
||||||
|
} label: {
|
||||||
|
if handler.testSuceeded {
|
||||||
|
Image(systemName: handler.testSuceeded ? "checkmark.circle" : "xmark.circle")
|
||||||
|
.modifier(foregroundColorStyle(handler.testSuceeded ? .green : .red))
|
||||||
|
} else {
|
||||||
|
Label("Test Connection", systemImage: "checkmark")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.disabled(!(handler.connected && handler.authorized))
|
||||||
}
|
}
|
||||||
.disabled(!(connected && handler.authorized))
|
}
|
||||||
|
|
||||||
Button("request a shell") {
|
|
||||||
handler.openShell()
|
|
||||||
}
|
|
||||||
|
|
||||||
Button("read from server") {
|
|
||||||
handler.readFromChannel()
|
|
||||||
}
|
|
||||||
|
|
||||||
TerminalView(handler: handler)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,19 @@ struct TerminalView: View {
|
|||||||
@ObservedObject var handler: SSHHandler
|
@ObservedObject var handler: SSHHandler
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
HStack {
|
||||||
|
Button("read from server") {
|
||||||
|
handler.readFromChannel()
|
||||||
|
}
|
||||||
|
.fixedSize()
|
||||||
|
Spacer()
|
||||||
|
Button("disconnect") {
|
||||||
|
handler.disconnect()
|
||||||
|
withAnimation { handler.testSuceeded = false }
|
||||||
|
withAnimation { handler.connected = false }
|
||||||
|
}
|
||||||
|
.disabled(!handler.connected)
|
||||||
|
}
|
||||||
TextViewController(text: $handler.terminal)
|
TextViewController(text: $handler.terminal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user