diff --git a/ShhShell.xcodeproj/project.pbxproj b/ShhShell.xcodeproj/project.pbxproj index d2b4cd1..b53386a 100644 --- a/ShhShell.xcodeproj/project.pbxproj +++ b/ShhShell.xcodeproj/project.pbxproj @@ -555,7 +555,7 @@ INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - IPHONEOS_DEPLOYMENT_TARGET = 14; + IPHONEOS_DEPLOYMENT_TARGET = 16; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -586,7 +586,7 @@ INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - IPHONEOS_DEPLOYMENT_TARGET = 14; + IPHONEOS_DEPLOYMENT_TARGET = 16; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/ShhShell/SSH/SSHHandler.swift b/ShhShell/SSH/SSHHandler.swift index 8886a3c..5bb0ce3 100644 --- a/ShhShell/SSH/SSHHandler.swift +++ b/ShhShell/SSH/SSHHandler.swift @@ -14,6 +14,8 @@ class SSHHandler: ObservableObject { private var channel: ssh_channel? @Published var authorized: Bool = false + @Published var connected: Bool = false + @Published var testSuceeded: Bool = false @Published var host: HostPr @Published var terminal: String = "" @@ -43,7 +45,7 @@ class SSHHandler: ObservableObject { return Data(base64Encoded: String(cString: data)) } - func connect() -> Bool { + func connect() { defer { getAuthMethods() self.host.key = getHostkey() @@ -53,7 +55,8 @@ class SSHHandler: ObservableObject { session = ssh_new() guard session != nil else { - return false + connected = false + return } ssh_options_set(session, SSH_OPTIONS_HOST, host.address) @@ -64,9 +67,11 @@ class SSHHandler: ObservableObject { if status != SSH_OK { logger.critical("connection not ok: \(status)") logSshGetError() - return false + connected = false + return } - return true + connected = true + return } func disconnect() { @@ -81,26 +86,34 @@ class SSHHandler: ObservableObject { host.key = nil } - func testExec() -> Bool { + func testExec() { 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 buffer: [Int] = Array(repeating: 0, count: 256) var nbytes: CInt 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) guard status == SSH_OK else { ssh_channel_free(channel) logger.critical("session opening error") logSshGetError() - return false + testSuceeded = false + return } status = ssh_channel_request_exec(channel, "uptime") @@ -109,7 +122,8 @@ class SSHHandler: ObservableObject { ssh_channel_free(channel) logger.critical("session opening error") logSshGetError() - return false + testSuceeded = false + return } nbytes = ssh_channel_read( @@ -125,7 +139,8 @@ class SSHHandler: ObservableObject { ssh_channel_free(channel) logger.critical("write error") logSshGetError() - return false + testSuceeded = false + return } nbytes = ssh_channel_read(channel, &buffer, UInt32(MemoryLayout.size(ofValue: Character.self)), 0) } @@ -135,14 +150,16 @@ class SSHHandler: ObservableObject { ssh_channel_free(channel) logger.critical("didnt read?") logSshGetError() - return false + testSuceeded = false + return } ssh_channel_send_eof(channel) ssh_channel_close(channel) ssh_channel_free(channel) print("testExec succeeded") - return true + testSuceeded = true + return } func authWithPubkey() -> Bool { diff --git a/ShhShell/Views/ContentView.swift b/ShhShell/Views/ContentView.swift index b62038f..0d4de58 100644 --- a/ShhShell/Views/ContentView.swift +++ b/ShhShell/Views/ContentView.swift @@ -9,79 +9,75 @@ import SwiftUI struct ContentView: View { @ObservedObject var handler: SSHHandler - @State var connected: Bool = false - @State var testSucceded: Bool? +// @State var connected: Bool = false var body: some View { - VStack { - Text(connected ? "connected" : "not connected") - .modifier(foregroundColorStyle(connected ? .green : .red)) - - Text(handler.authorized ? "authorized" : "unauthorized") - .modifier(foregroundColorStyle(handler.authorized ? .green : .red)) - - if let testSucceded = testSucceded { - Image(systemName: testSucceded ? "checkmark.circle" : "xmark.circle") - .modifier(foregroundColorStyle(testSucceded ? .green : .red)) - } - - if handler.host.key != nil { - Text("Hostkey: \(handler.host.key!.base64EncodedString())") - } - - TextField("address", text: $handler.host.address) - .textFieldStyle(.roundedBorder) - - TextField( - "port", - text: Binding( - get: { String(handler.host.port) }, - set: { handler.host.port = Int($0) ?? 22} ) - ) + NavigationStack { + List { + HStack { + Text(handler.connected ? "connected" : "not connected") + .modifier(foregroundColorStyle(handler.connected ? .green : .red)) + + Text(handler.authorized ? "authorized" : "unauthorized") + .modifier(foregroundColorStyle(handler.authorized ? .green : .red)) + } + +// if let testSucceded = testSucceded { +// Image(systemName: testSucceded ? "checkmark.circle" : "xmark.circle") +// .modifier(foregroundColorStyle(testSucceded ? .green : .red)) +// } + + if handler.host.key != nil { + Text("Hostkey: \(handler.host.key!.base64EncodedString())") + } + + TextField("address", text: $handler.host.address) + .textFieldStyle(.roundedBorder) + + TextField( + "port", + text: Binding( + get: { String(handler.host.port) }, + set: { handler.host.port = Int($0) ?? 22} ) + ) .keyboardType(.numberPad) .textFieldStyle(.roundedBorder) - - TextField("username", text: $handler.host.username) - .textFieldStyle(.roundedBorder) - - TextField("password", text: $handler.host.password) - .textFieldStyle(.roundedBorder) - - Button("connect") { - if handler.connect() { - withAnimation { connected = true } + + TextField("username", text: $handler.host.username) + .textFieldStyle(.roundedBorder) + + TextField("password", text: $handler.host.password) + .textFieldStyle(.roundedBorder) + + Button() { + handler.connect() + let _ = handler.authWithPw() + handler.openShell() + } label: { + Label("Connect", systemImage: "powerplug.portrait") } - handler.authWithPw() - } - .disabled(connected) - - Button("disconnect") { - handler.disconnect() - 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) + + NavigationLink() { + TerminalView(handler: handler) + } label: { + Label("Open Terminal", systemImage: "apple.terminal") } + .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) - } + } } } diff --git a/ShhShell/Views/TerminalView.swift b/ShhShell/Views/TerminalView.swift index b3e8c83..db3cf38 100644 --- a/ShhShell/Views/TerminalView.swift +++ b/ShhShell/Views/TerminalView.swift @@ -12,6 +12,19 @@ struct TerminalView: View { @ObservedObject var handler: SSHHandler 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) } }