// // NCConfigServer.swift // Nextcloud // // Created by Marino Faggiana on 05/12/22. // Copyright © 2022 Marino Faggiana. All rights reserved. // import Foundation import Swifter import NextcloudKit @objc class NCConfigServer: NSObject, UIActionSheetDelegate { // MARK: Singleton @objc static let shared = NCConfigServer() // Start service @objc func startService(url: URL) { let defaultSessionConfiguration = URLSessionConfiguration.default let defaultSession = URLSession(configuration: defaultSessionConfiguration) var urlRequest = URLRequest(url: url) urlRequest.headers = NKCommon.shared.getStandardHeaders(nil, customUserAgent: nil) let dataTask = defaultSession.dataTask(with: urlRequest) { (data, response, error) in if let error = error { let error = NKError(errorCode: error._code, errorDescription: error.localizedDescription) NCContentPresenter.shared.showInfo(error: error) } else if let data = data { DispatchQueue.main.async { self.start(data: data) } } } dataTask.resume() } private enum ConfigState: Int { case Stopped, Ready, InstalledConfig, BackToApp } internal let listeningPort: in_port_t = 8080 internal var configName: String = "Profile install" private var localServer: HttpServer! private var returnURL: String = "" private var configData: Data! private var serverState: ConfigState = .Stopped private var registeredForNotifications = false private var backgroundTask = UIBackgroundTaskIdentifier.invalid deinit { unregisterFromNotifications() } // MARK:- Control functions internal func start(data: Data) { self.configData = data self.localServer = HttpServer() self.setupHandlers() let page = self.baseURL(pathComponent: "install/") let url = URL(string: page)! if UIApplication.shared.canOpenURL(url as URL) { do { try localServer.start(listeningPort, forceIPv4: false, priority: .default) serverState = .Ready registerForNotifications() UIApplication.shared.open(url) } catch { let error = NKError(errorCode: error._code, errorDescription: error.localizedDescription) NCContentPresenter.shared.showInfo(error: error) self.stop() } } } internal func stop() { if serverState != .Stopped { serverState = .Stopped unregisterFromNotifications() } } // MARK:- Private functions private func setupHandlers() { localServer["/install"] = { request in switch self.serverState { case .Stopped: return .notFound() case .Ready: self.serverState = .InstalledConfig return HttpResponse.raw(200, "OK", ["Content-Type": "application/x-apple-aspen-config"], { writer in do { try writer.write(self.configData) } catch { print("Failed to write response data") } }) case .InstalledConfig: return .movedPermanently(self.returnURL) case .BackToApp: let page = self.basePage(pathComponent: nil) return .ok(.html(page)) } } } private func baseURL(pathComponent: String?) -> String { var page = "http://localhost:\(listeningPort)" if let component = pathComponent { page += "/\(component)" } return page } private func basePage(pathComponent: String?) -> String { var page = "" + "