29 |
30 |
31 |

32 |
35 |
lets you connect without concern whether running on any platform, any time, any where.
36 |
37 | Thank you for using Omniedge.
Please check us out on
38 | omniedge.io
39 |
40 |
You can close this tab now.
41 |
42 |
43 |

44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # OmniEdge-macOS
2 |
3 | The OmniEdge GUI version for macOS, API implementation is still understand developemnt.
4 |
5 | >Bring the intranet on the internet
6 |
7 |
8 | [](http://www.gnu.org/licenses/gpl-3.0)
9 |
10 | [🤝 Website](https://omniedge.io)
11 | [💬 Twitter](https://twitter.com/omniedgeio)
12 | [😇 Discord](https://discord.gg/d4faRPYj)
13 |
14 | A cross-platform private network tool for developers.
15 |
16 | 
17 |
18 |
19 |
20 | ## Install
21 |
22 | ### Install OmniEdge Cli
23 |
24 | ```bash
25 | curl https://omniedge.io/install/omniedge-install.sh | bash
26 | ```
27 |
28 | ### Install OmniEdge Gui Client
29 |
30 | - [Android: OmniEdge.apk](https://omniedge.io/install/download/0.2.2/omniedge-release-v0.2.2.apk)
31 | - [macOS cli](https://omniedge.io/install/download/0.2.3/omniedgecli-macos-latest.zip)
32 | - [Windows](https://omniedge.io/install/download/0.2.3/omniedge-setup-0.2.3.exe)
33 | - [Linux Cli](https://github.com/omniedgeio/app-release/releases/tag/v0.2.3)
34 | - [iOS & M1 Mac on App Store](https://apps.apple.com/us/app/omniedgenew/id1603005893)
35 | - [Synology](https://omniedge.io/download/synology)
36 | - [Raspberry Pi, ARM, Nvidia Jetson](https://github.com/omniedgeio/app-release/releases/tag/v0.2.3)
37 |
38 |
39 | ## Cli Command
40 |
41 | ### Login
42 |
43 | - Login By Password
44 |
45 | ```shell
46 | omniedge login -u xxx@xxx.com
47 | ```
48 |
49 | - Login By Secret-Key
50 |
51 | You can generate secret-key on omniedge web.
52 |
53 | ```shell
54 | omniedge login -s xxxxxx
55 | ```
56 |
57 | ### Join
58 |
59 | you can just call `omniedge join`, it will automatically prompt
60 | the available network for you to choose. And you can
61 | also add one parameter `-n` to specify the network id manually.
62 |
63 | And then, enjoy the omniedge network.
64 |
65 | ```shell
66 | omniedge join
67 | // or
68 | omniedge join -n "virtual-network-id"
69 | ```
70 |
71 | ## Protocol
72 |
73 | [n2n](https://github.com/ntop/n2n)
74 |
75 | ## Resources
76 |
77 | - Architecture: https://omniedge.io/docs/article/architecture
78 | - Install: https://omniedge.io/docs/article/install
79 | - Cases: https://omniedge.io/docs/article/cases
80 | - Compare: https://omniedge.io/docs/article/compare
81 | - Performance: https://omniedge.io/docs/article/performance
82 | - Dashboard: https://omniedge.io/docs/article/admin
83 | - [n2n](https://github.com/ntop/n2n)
84 |
85 |
86 | ## Contributing Guildlines
87 |
88 | Check the tempalte into .github folder to report an issue or submit a PR:
89 | 1. ISSUE_TEMPLATE.md
90 | 2. PULL_REQUEST_TEMPLATE.md
91 |
92 | ## How to get started?
93 |
94 | 1. If you only need a convenient connectivity service
95 | Just visit https://omniedge.io/download and download the apps for your platform.
96 |
97 | 2. If you are an experienced programmer
98 | You can prepare your own supernode and build the client to reach your own target accroding to the following `Compiler and debugger` Section.
99 |
100 | ## Compiler and debugger
101 |
102 | Latest version of Xcode, run,
103 |
104 | ```bash
105 | carthage update
106 | carthage update --use-xcframeworks
107 | ```
108 |
109 |
110 | ## Contributors
111 |
112 | @kidylee @EbenDang
113 |
114 | ## About US
115 | [OmniEdge](https://omniedge.io) is primiary developed by the people at [https://github.com/orgs/omniedgeio/people](https://github.com/orgs/omniedgeio/people).
116 |
--------------------------------------------------------------------------------
/Services/AppService.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppService.swift
3 | // Omniedge
4 | //
5 | // Created by Yanbo Dang on 16/7/2022.
6 | //
7 |
8 | import Foundation
9 |
10 | protocol IAppService {
11 |
12 | }
13 |
14 | class AppService: IAppService {
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/Services/AuthService.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AuthService.swift
3 | // Omniedge
4 | //
5 | // Created by Yanbo Dang on 16/7/2022.
6 | //
7 |
8 | import Foundation
9 | import AppKit
10 |
11 | protocol AuthServiceDelegate: AnyObject {
12 | func didLoginCompleted(token: String?)
13 | }
14 |
15 | protocol IAuthService: IService {
16 | var delegate: AuthServiceDelegate? { get set }
17 | func login()
18 | }
19 |
20 | class AuthService: BaseService, IAuthService {
21 |
22 | var token: String? {
23 | get {
24 | return self.authToken
25 | }
26 | }
27 |
28 | weak var delegate: AuthServiceDelegate?
29 |
30 | private var httpService: IHttpService
31 | private var authToken: String?
32 |
33 | init(httpService: IHttpService) {
34 | self.httpService = httpService
35 | super.init()
36 | }
37 |
38 |
39 | override func initService() {
40 | }
41 |
42 | func login() {
43 |
44 | self.httpService.sendGetRequest(url: ApiEndPoint.authSession, completed: {
45 | [weak self] (result: Result
, OmError>) in
46 | switch result {
47 | case .success(let response):
48 | if let authModel = response.data {
49 | self?.monitorSessionCodeWSEvent(sessionCode: authModel.sessionId)
50 | self?.onAuthurized(model: authModel)
51 | } else {
52 | self?.handleError(error: .invalidRsp)
53 | }
54 |
55 | case .failure(let error):
56 | self?.handleError(error: error)
57 | }
58 | })
59 | }
60 |
61 | private func onAuthurized(model: AuthModel) {
62 | guard let url = URL(string: model.authUrl) else {
63 | return
64 | }
65 |
66 | NSWorkspace.shared.open(url)
67 | }
68 |
69 | private func monitorSessionCodeWSEvent(sessionCode: String) {
70 | self.httpService.listenSocket(url: "\(ApiEndPoint.wsEndPoint)/login/session/\(sessionCode)", received: {
71 | [weak self] result in
72 |
73 | switch result {
74 | case .success(let msgData):
75 | self?.didReceivedAuthSocketMessage(message: msgData)
76 | case .failure(let error):
77 | self?.handleError(error: error)
78 | }
79 | })
80 | }
81 |
82 | private func didReceivedAuthSocketMessage(message: Data?) {
83 | guard let message = message else {
84 | return
85 | }
86 |
87 | do {
88 | let result = try JSONDecoder().decode(Dictionary.self, from: message)
89 | let token = result["token"]
90 | self.delegate?.didLoginCompleted(token: token)
91 | } catch let error {
92 | self.handleError(error: .other(error))
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/Services/BaseService.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BaseService.swift
3 | // Omniedge
4 | //
5 | // Created by Yanbo Dang on 16/7/2022.
6 | //
7 |
8 | import Foundation
9 |
10 | class BaseService {
11 |
12 | init() {
13 | self.initService()
14 | }
15 |
16 | func initService() {
17 |
18 | }
19 |
20 | func handleError(error: OmError){
21 | print(error)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Services/CacheService.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CacheService.swift
3 | // Omniedge
4 | //
5 | // Created by Yanbo Dang on 23/7/2022.
6 | //
7 |
8 | import Foundation
9 |
10 | protocol ICacheService {
11 | func saveValue(value: Any?, key: String)
12 | func getValue(forKey: String) -> Any?
13 | func clearValueForKey(key: String)
14 | }
15 |
16 | class CacheService: BaseService, ICacheService {
17 |
18 | private var userDefault: UserDefaults = UserDefaults.standard
19 |
20 | func saveValue(value: Any?, key: String) {
21 | self.userDefault.setValue(value, forKey: key)
22 | self.userDefault.synchronize()
23 | }
24 |
25 | func getValue(forKey: String) -> Any? {
26 | return self.userDefault.value(forKey: forKey)
27 | }
28 |
29 | func clearValueForKey(key: String) {
30 | self.userDefault.removeObject(forKey: key)
31 | self.userDefault.synchronize()
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Services/HttpService.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HttpService.swift
3 | // Omniedge
4 | //
5 | // Created by Yanbo Dang on 15/7/2022.
6 | //
7 |
8 | import Foundation
9 |
10 | protocol IHttpService: IService {
11 | var token: String? { get set }
12 |
13 | func sendGetRequest(url: String, completed: @escaping (Result, OmError>) -> Void)
14 | func sendPostRequest(url: String, payload: S, completed: @escaping (Result, OmError>) -> Void)
15 |
16 | func listenSocket(url: String, received: @escaping (Result) -> Void)
17 | }
18 |
19 | class HttpService: BaseService, IHttpService {
20 |
21 | enum HttpMethodType: String {
22 | case httpGet = "GET"
23 | case httpPost = "POST"
24 | }
25 |
26 | var token: String?
27 |
28 | private var session: URLSession?
29 | private var baseEndPoint = ApiEndPoint.baseApi
30 | private var jsonDecoder: JSONDecoder = JSONDecoder()
31 |
32 | override init() {
33 | super.init()
34 | }
35 |
36 | override func initService() {
37 | self.session = URLSession(configuration: URLSessionConfiguration.default, delegate: nil, delegateQueue: nil)
38 |
39 | let dateFormatter = DateFormatter()
40 | dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
41 | self.jsonDecoder.dateDecodingStrategy = .formatted(dateFormatter)
42 | }
43 |
44 | func sendGetRequest(url: String, completed: @escaping (Result, OmError>) -> Void) {
45 |
46 | guard let session = self.session,
47 | let request = self.generateRequest(url: url, httpMethodType: .httpGet) else {
48 | completed(.failure(.invalidUrl))
49 | return
50 | }
51 |
52 | let task = session.dataTask(with: request) { (data, response, error) in
53 | if error != nil {
54 | completed(.failure(.other(error!)))
55 | return
56 | }
57 |
58 | guard let data = data else {
59 | completed(.failure(.invalidRsp))
60 | return
61 | }
62 |
63 | #if DEBUG
64 | data.printJson()
65 | #endif
66 |
67 | do {
68 | let response = try self.jsonDecoder.decode(Response.self, from: data)
69 | completed(.success(response))
70 | } catch let error {
71 | completed(.failure(.other(error)))
72 | }
73 | }
74 |
75 | task.resume()
76 | }
77 |
78 | func sendPostRequest(url: String, payload: S, completed: @escaping (Result, OmError>) -> Void) {
79 | guard let session = self.session,
80 | var request = self.generateRequest(url: url, httpMethodType: .httpPost) else {
81 | completed(.failure(.invalidUrl))
82 | return
83 | }
84 |
85 | do {
86 | let jsonData = try JSONEncoder().encode(payload)
87 | request.httpBody = jsonData
88 | request.setValue("application/json", forHTTPHeaderField: "Content-Type")
89 | } catch let error {
90 | completed(.failure(.other(error)))
91 | return
92 | }
93 |
94 | let task = session.dataTask(with: request) { (data, response, error) in
95 | if error != nil {
96 | completed(.failure(.other(error!)))
97 | return
98 | }
99 |
100 | guard let data = data else {
101 | return
102 | }
103 |
104 | #if DEBUG
105 | data.printJson()
106 | #endif
107 |
108 | do {
109 |
110 | let restReponse = try self.jsonDecoder.decode(Response.self, from: data)
111 | if(restReponse.code == 200) {
112 | completed(.success(restReponse))
113 | } else {
114 | completed(.failure(.errCode(restReponse.code, restReponse.message ?? String.Empty)))
115 | }
116 | } catch let error {
117 | print(error)
118 | completed(.failure(.other(error)))
119 | }
120 | }
121 |
122 | task.resume()
123 | }
124 |
125 |
126 |
127 | func listenSocket(url: String, received: @escaping (Result) -> Void ) {
128 | let urlSession = URLSession(configuration: URLSessionConfiguration.default)
129 | guard let url = URL(string: url) else {
130 | return
131 | }
132 |
133 | let sokcetTask = urlSession.webSocketTask(with: url)
134 | sokcetTask.resume()
135 | sokcetTask.receive { result in
136 | switch result {
137 | case .success(let message):
138 | self.didReceivedSocketMessage(message: message, completed: received)
139 | case .failure(let error):
140 | self.handleError(error: .other(error))
141 | }
142 | }
143 | }
144 |
145 | private func didReceivedSocketMessage(message: URLSessionWebSocketTask.Message, completed: (Result) -> Void ) {
146 | switch message {
147 | case .string(let msg):
148 | completed(.success(msg.data(using: .utf8)))
149 | case .data(let data):
150 | completed(.success(data))
151 | @unknown default:
152 | fatalError()
153 | }
154 | }
155 |
156 | private func generateRequest(url: String, httpMethodType: HttpMethodType) -> URLRequest? {
157 | guard let url = URL(string: ApiEndPoint.baseApi + url) else {
158 | return nil
159 | }
160 |
161 | var request = URLRequest(url: url)
162 | request.httpMethod = httpMethodType.rawValue
163 | guard let token = token else {
164 | return request
165 | }
166 |
167 | request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
168 | return request
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/Services/IService.swift:
--------------------------------------------------------------------------------
1 | //
2 | // IService.swift
3 | // Omniedge
4 | //
5 | // Created by Yanbo Dang on 16/7/2022.
6 | //
7 |
8 | import Foundation
9 |
10 | protocol IService {
11 |
12 | func initService()
13 | }
14 |
--------------------------------------------------------------------------------
/Services/LocatorService.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LocatorService.swift
3 | // Omniedge
4 | //
5 | // Created by Yanbo Dang on 16/7/2022.
6 | //
7 |
8 | import Foundation
9 |
10 | protocol ILocatorService {
11 | func register(instance: T)
12 | func register(recipe: @escaping () -> T)
13 | func resolve() -> T
14 | }
15 |
16 | final class LocatorService: ILocatorService {
17 | enum RegistryRec{
18 | case Instance(Any)
19 | case Recipe(() -> Any)
20 |
21 | func unwap() -> Any{
22 | switch self{
23 | case .Instance(let instance):
24 | return instance
25 | case .Recipe(let recipe):
26 | return recipe()
27 | }
28 | }
29 | }
30 |
31 | lazy private var repository: Dictionary = [:]
32 |
33 | private static var instance : LocatorService = {
34 | return LocatorService()
35 | }()
36 |
37 | private init(){
38 | }
39 |
40 | class func shareInstance() -> LocatorService {
41 | return instance
42 | }
43 |
44 | func register(instance: T) {
45 | let key = typeNmae(some: T.self)
46 | self.repository[key] = .Instance(instance)
47 | }
48 |
49 | func register(recipe: @escaping () -> T) {
50 | let key = typeNmae(some: T.self)
51 | self.repository[key] = .Recipe(recipe)
52 | }
53 |
54 | func resolve() -> T {
55 | let key = self.typeNmae(some: T.self)
56 | var instance : T? = nil
57 | if let record = self.repository[key]{
58 | instance = record.unwap() as? T
59 | switch record {
60 | case .Recipe:
61 | if let instance = instance {
62 | self.register(instance: instance)
63 | }
64 | default:
65 | break
66 | }
67 | }
68 |
69 | guard let instance = instance else {
70 | fatalError()
71 | }
72 |
73 | return instance
74 | }
75 |
76 | private func typeNmae(some: Any) -> String {
77 | return (some is Any.Type) ? "\(some)" : "\(type(of: some))"
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/Services/OmniService.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppService.swift
3 | // Omniedge
4 | //
5 | // Created by Yanbo Dang on 15/7/2022.
6 | //
7 |
8 | import Foundation
9 | import AppKit
10 |
11 | protocol OmniServiceDelegate: AnyObject {
12 | func didLoginSuccess()
13 | func didLoginFailed()
14 | func didLogout()
15 | func didNetworksLoaded(networks: [VirtualNetworkModel])
16 | func didError(error: OmError)
17 | func didDeviceJoined(deviceModel: DeviceRegisterModel?, joinedModel: JoinDeviceMode?, connected: Bool)
18 | func clearRegistedDevice()
19 | }
20 |
21 | protocol IOmniService: IService {
22 | var delegate: OmniServiceDelegate? { get set }
23 | var networkService: IVirtualNetworkService { get }
24 | var hasLoggedIn: Bool { get }
25 |
26 | func login()
27 | func logout()
28 | func getCachedNetworkConfig() -> Data?
29 |
30 | func terminate()
31 | }
32 |
33 | class OmniService: IOmniService {
34 |
35 | var hasLoggedIn: Bool {
36 | get {
37 | return self.token != nil
38 | }
39 | }
40 |
41 | weak var delegate: OmniServiceDelegate?
42 |
43 | var networkService: IVirtualNetworkService {
44 | get {
45 | guard let virtualNetworkService = self.curVirtualNetworkService else {
46 | let networkService: IVirtualNetworkService = self.locatorService.resolve()
47 | self.curVirtualNetworkService = networkService
48 | self.curVirtualNetworkService?.delegate = self
49 | return networkService
50 | }
51 |
52 | return virtualNetworkService
53 | }
54 | }
55 |
56 | private var httpService: IHttpService {
57 | get {
58 |
59 | guard let httpService = self.curHttpService else {
60 | let httpService: IHttpService = self.locatorService.resolve()
61 | self.curHttpService = httpService
62 | return httpService
63 | }
64 |
65 | return httpService
66 | }
67 | }
68 |
69 | private var authService: IAuthService {
70 | get {
71 | guard let authService = self.curAuthService else {
72 | let authService: IAuthService = self.locatorService.resolve()
73 | self.curAuthService = authService
74 | self.curAuthService?.delegate = self
75 | return authService
76 | }
77 |
78 | return authService
79 | }
80 | }
81 |
82 | private var locatorService: ILocatorService
83 | private var curHttpService: IHttpService?
84 | private var curAuthService: IAuthService?
85 | private var curVirtualNetworkService: IVirtualNetworkService?
86 | private var cacheService: ICacheService
87 |
88 | private var token: String?
89 |
90 | init(locatorService: ILocatorService) {
91 | self.locatorService = locatorService
92 | self.cacheService = self.locatorService.resolve()
93 | }
94 |
95 | func initService() {
96 | let xpcService: IXPCService = self.locatorService.resolve()
97 | let authService = AuthService(httpService: self.httpService)
98 | let networkService = VirtualNetworkService(httpService: self.httpService, xpcService: xpcService)
99 |
100 | self.locatorService.register(instance: authService as IAuthService)
101 | self.locatorService.register(instance: networkService as IVirtualNetworkService)
102 |
103 | xpcService.installAndConnectHeperTool()
104 | }
105 |
106 | func login() {
107 | self.authService.login()
108 | }
109 |
110 | func logout() {
111 | self.token = nil
112 | self.delegate?.didLogout()
113 | DispatchQueue.main.async {
114 | (NSApplication.shared.delegate as? AppDelegate)?.didLogin(login: false)
115 | }
116 | }
117 |
118 | func joinLocalDevice(vnId: String) {
119 | self.networkService.joinDeviceInNetwork(vnId: vnId)
120 | }
121 |
122 | func getCachedNetworkConfig() -> Data? {
123 | let cacheService: ICacheService = self.locatorService.resolve()
124 | let networkConfigData = cacheService.getValue(forKey: UserDefaultKeys.NetworkConfig)
125 | return networkConfigData as? Data
126 | }
127 |
128 | func terminate() {
129 | let xpcService: IXPCService = self.locatorService.resolve()
130 | xpcService.disconnect()
131 | }
132 |
133 | private func updateDevice(connected: Bool) {
134 | let registedDeviceData: Data? = self.cacheService.getValue(forKey: UserDefaultKeys.RegisterDevice) as? Data
135 | let joinedDeviceData: Data? = self.cacheService.getValue(forKey: UserDefaultKeys.JoinedDevice) as? Data
136 |
137 | var registerDevice: DeviceRegisterModel?
138 | var joinedDevice: JoinDeviceMode?
139 |
140 | if registedDeviceData != nil {
141 | registerDevice = try? JSONDecoder().decode(DeviceRegisterModel.self, from: registedDeviceData!)
142 | }
143 |
144 | if joinedDeviceData != nil {
145 | joinedDevice = try? JSONDecoder().decode(JoinDeviceMode.self, from: joinedDeviceData!)
146 | }
147 |
148 | self.delegate?.didDeviceJoined(deviceModel: registerDevice, joinedModel: joinedDevice, connected: connected)
149 | }
150 |
151 | // MARK: - Private functions -
152 | private func getRemoteNetworkList() {
153 | self.networkService.loadNetworks()
154 | }
155 |
156 | private func registerLocalDevice() {
157 | self.networkService.registerDevice()
158 | }
159 | }
160 |
161 | extension OmniService: AuthServiceDelegate {
162 | func didLoginCompleted(token: String?) {
163 | self.curHttpService?.token = token
164 | self.token = token
165 | var loggedIn = false
166 |
167 | if token == nil {
168 | self.delegate?.didLoginFailed()
169 | } else {
170 | self.updateDevice(connected: false)
171 | self.delegate?.didLoginSuccess()
172 | self.registerLocalDevice()
173 | self.getRemoteNetworkList()
174 | loggedIn = true
175 | }
176 |
177 | DispatchQueue.main.async {
178 | (NSApplication.shared.delegate as? AppDelegate)?.didLogin(login: loggedIn)
179 | }
180 | }
181 | }
182 |
183 | extension OmniService: VirtualNetworkServiceDelegate {
184 | func didNetworkListLoaded(networks: [VirtualNetworkModel]) {
185 | self.delegate?.didNetworksLoaded(networks: networks)
186 | }
187 |
188 | func didJoinedDevice(model: JoinDeviceMode) {
189 | var data: Data?
190 | do {
191 | data = try JSONEncoder().encode(model)
192 |
193 | } catch let error {
194 | self.delegate?.didError(error: .other(error))
195 | return
196 | }
197 |
198 | guard let data = data else {
199 | return
200 | }
201 |
202 | // save it
203 | self.cacheService.saveValue(value: data, key: UserDefaultKeys.JoinedDevice)
204 |
205 | self.networkService.connectNetwork(dataOfNetworkConfig: data) {
206 | [weak self] success in
207 | if !success {
208 | Utils.alert(title: "Tuntap not detected", description: "Tuntap is required to enable the network, please install it according the instruction: https://omniedge.io/docs/article/install/macos.", .critical)
209 | }
210 |
211 | self?.updateDevice(connected: success)
212 | }
213 | }
214 |
215 | func didRegisteredDeviceFailed() {
216 | self.cacheService.clearValueForKey(key: UserDefaultKeys.RegisterDevice)
217 | self.updateDevice(connected: false)
218 | self.delegate?.clearRegistedDevice()
219 | }
220 |
221 | func didRegisteredDevice(model: DeviceRegisterModel) {
222 | var data: Data?
223 | do {
224 | data = try JSONEncoder().encode(model)
225 |
226 | } catch let error {
227 | self.delegate?.didError(error: .other(error))
228 | return
229 | }
230 |
231 | guard let data = data else {
232 | return
233 | }
234 |
235 | // save it
236 | self.cacheService.saveValue(value: data, key: UserDefaultKeys.RegisterDevice)
237 |
238 | self.updateDevice(connected: false)
239 | }
240 | }
241 |
--------------------------------------------------------------------------------
/Services/VirtualNetworkService.swift:
--------------------------------------------------------------------------------
1 | //
2 | // VirtualNetworkService.swift
3 | // Omniedge
4 | //
5 | // Created by Yanbo Dang on 16/7/2022.
6 | //
7 |
8 | import Foundation
9 |
10 | protocol VirtualNetworkServiceDelegate: AnyObject {
11 | func didNetworkListLoaded(networks: [VirtualNetworkModel])
12 | func didRegisteredDevice(model: DeviceRegisterModel)
13 | func didJoinedDevice(model: JoinDeviceMode)
14 | func didRegisteredDeviceFailed()
15 | }
16 |
17 | protocol IVirtualNetworkService {
18 | var failedRegisteDev: Bool { get }
19 |
20 | var delegate: VirtualNetworkServiceDelegate? { get set }
21 | var curConnectedNetworkId: String? { get }
22 | func loadNetworks()
23 | func connectNetwork(dataOfNetworkConfig: Data, completed: @escaping (_ successed: Bool) -> Void)
24 | func disconnectNetwork()
25 | func registerDevice()
26 | func joinDeviceInNetwork(vnId: String)
27 | }
28 |
29 | class VirtualNetworkService: BaseService, IVirtualNetworkService {
30 |
31 | weak var delegate: VirtualNetworkServiceDelegate?
32 |
33 | var curConnectedNetworkId: String? {
34 | get {
35 | return self.lastConnectedVNId
36 | }
37 | }
38 |
39 | var failedRegisteDev: Bool {
40 | get {
41 | return self.registerDevFailed
42 | }
43 | }
44 |
45 | private var httpService: IHttpService
46 | private var xpcService: IXPCService
47 | private var deviceRegisterModel: DeviceRegisterModel?
48 | private var deviceJoinedModel: JoinDeviceMode?
49 | private var deviceModel: DeviceModel?
50 | private var lastConnectedVNId: String?
51 | private var networks: [VirtualNetworkModel] = []
52 | private var registerDevFailed: Bool = false
53 |
54 | init(httpService: IHttpService, xpcService: IXPCService) {
55 | self.httpService = httpService
56 | self.xpcService = xpcService
57 | super.init()
58 | }
59 |
60 | override func initService() {
61 | self.deviceModel = Utils.getDeviceInfo()
62 | }
63 |
64 | func loadNetworks() {
65 |
66 | self.httpService.sendGetRequest(url: ApiEndPoint.virtualNetworkList, completed: {
67 | [weak self] (result: Result, OmError>) in
68 | switch result {
69 | case .success(let response):
70 | if(response.code == 200) {
71 | self?.didLoadNetworkList(networks: response.data)
72 | } else {
73 | self?.handleError(error: .errCode(response.code, response.message ?? String.Empty))
74 | }
75 | case .failure(let error):
76 | self?.handleError(error: error)
77 | }
78 | })
79 | }
80 |
81 | func connectNetwork(dataOfNetworkConfig: Data, completed: @escaping (_ successed: Bool) -> Void) {
82 | // check if the tuntapInstalled
83 | if !self.hasTuntapInstalled() {
84 | completed(false)
85 | return
86 | }
87 |
88 | self.terminateActiveTapConnection()
89 | print("Start connection");
90 | self.xpcService.connect(dataOfNetworkConfig: dataOfNetworkConfig) { (success, error) in
91 | completed(success)
92 | guard let error = error else {
93 | return
94 | }
95 | print(error)
96 | }
97 | }
98 |
99 | func disconnectNetwork() {
100 | self.xpcService.disconnect()
101 | }
102 |
103 | func registerDevice() {
104 | self.httpService.sendPostRequest(url: ApiEndPoint.registerDevice, payload: self.deviceModel) {
105 | [weak self] (result: Result, OmError>) in
106 | switch result {
107 | case .success(let response):
108 | self?.onDeviceRegister(model: response.data)
109 | case .failure(let error):
110 | self?.registerDevFailed = true
111 | self?.delegate?.didRegisteredDeviceFailed()
112 | self?.handleError(error: error)
113 | }
114 | }
115 | }
116 |
117 | func joinDeviceInNetwork(vnId: String) {
118 | if self.lastConnectedVNId != nil && self.lastConnectedVNId! != vnId {
119 | self.disconnectNetwork()
120 | }
121 |
122 | guard let deviceId = self.deviceRegisterModel?.deviceId else {
123 | return
124 | }
125 | let payload: [String: String] = ["deviceId" : deviceId]
126 | let joinUrl = "\(ApiEndPoint.virtualNetworkList)\(vnId)/devices/\(deviceId)/join";
127 | self.httpService.sendPostRequest(url: joinUrl, payload: payload) {
128 | [weak self] (result: Result< Response, OmError>) in
129 | switch result {
130 | case .success(let response):
131 | self?.onDeviceJoined(model: response.data, virtualNetworkId: vnId)
132 | case .failure(let error):
133 | self?.handleError(error: error)
134 | }
135 | }
136 | }
137 |
138 | // MARK: - Private functions -
139 | private func didLoadNetworkList(networks: [VirtualNetworkModel]?) {
140 | guard let networks = networks else {
141 | return
142 | }
143 |
144 | self.networks.removeAll()
145 | self.networks.append(contentsOf: networks)
146 | self.delegate?.didNetworkListLoaded(networks: networks)
147 | }
148 |
149 | private func hasTuntapInstalled() -> Bool {
150 | return FileManager.default.fileExists(atPath: "/dev/tap0")
151 | }
152 |
153 | private func onDeviceRegister(model: DeviceRegisterModel?) {
154 | guard let model = model else {
155 | return
156 | }
157 | registerDevFailed = false
158 | self.deviceRegisterModel = model
159 | self.delegate?.didRegisteredDevice(model: model)
160 | }
161 |
162 | private func onDeviceJoined(model: JoinDeviceMode?, virtualNetworkId: String) {
163 | guard let model = model else {
164 | return
165 | }
166 |
167 | self.lastConnectedVNId = virtualNetworkId
168 | let vnName = self.networks.first { item in
169 | item.vnId == virtualNetworkId
170 | }?.vnName
171 | self.deviceJoinedModel = model
172 | self.deviceJoinedModel?.setVnId(vnId: virtualNetworkId)
173 | self.deviceJoinedModel?.setVnName(vnName: vnName ?? String.Empty)
174 |
175 |
176 | self.delegate?.didJoinedDevice(model: self.deviceJoinedModel!)
177 | }
178 |
179 | private func terminateActiveTapConnection() {
180 | for _ in 0 ..< 6 {
181 | let output = runShellAndOutput("ifconfig | grep tap0 | head -c 4")
182 | if output?.starts(with: "tap") ?? false {
183 | print("Detected an active tap connection, terminate it");
184 | self.disconnectNetwork()
185 | sleep(1)
186 | //usleep(useconds_t(5 * 1000) * 100)
187 | print("after 1s delay, check it again");
188 | } else {
189 | print("No active connection found");
190 | break
191 | }
192 | }
193 | }
194 |
195 | @discardableResult
196 | // func runShellAndOutput(_ command: String) -> (Int32, String?) {
197 | private func runShellAndOutput(_ command: String) -> String? {
198 | let task = Process()
199 | task.launchPath = "/bin/bash"
200 | task.arguments = ["-c", command]
201 |
202 | let pipe = Pipe()
203 | task.standardOutput = pipe
204 | task.standardError = pipe
205 |
206 | task.launch()
207 |
208 | let data = pipe.fileHandleForReading.readDataToEndOfFile()
209 | let output = String(data: data, encoding: .utf8)
210 |
211 | task.waitUntilExit()
212 |
213 | return output
214 | // return (task.terminationStatus, output)
215 | }
216 |
217 | @discardableResult
218 | func runShellWithArgsAndOutput(_ args: String...) -> (Int32, String?) {
219 | let task = Process()
220 |
221 | task.launchPath = "/usr/bin/env"
222 | task.arguments = args
223 |
224 | let pipe = Pipe()
225 | task.standardOutput = pipe
226 | task.standardError = pipe
227 |
228 | task.launch()
229 |
230 | let data = pipe.fileHandleForReading.readDataToEndOfFile()
231 | let output = String(data: data, encoding: .utf8)
232 |
233 | task.waitUntilExit()
234 |
235 | return (task.terminationStatus, output)
236 | }
237 | }
238 |
--------------------------------------------------------------------------------
/Services/XPCService.swift:
--------------------------------------------------------------------------------
1 | //
2 | // XCPService.swift
3 | // Omniedge
4 | //
5 | // Created by Yanbo Dang on 15/7/2022.
6 | //
7 |
8 | import Foundation
9 | import AppKit
10 |
11 | protocol IXPCService: IService {
12 | func installAndConnectHeperTool()
13 | func connect(dataOfNetworkConfig: Data, completed: @escaping (Bool, Error?) -> Void)
14 | func disconnect()
15 | }
16 |
17 | class XPCService: BaseService, IXPCService {
18 | private var XPCConnection: NSXPCConnection?
19 | private var helperTool: HelperTool?
20 |
21 | func installAndConnectHeperTool() {
22 | if !FileManager.default.fileExists(atPath: "/Library/PrivilegedHelperTools/\(XPCConstant.HelperMachLabel)"){
23 |
24 | self.alertInstall("Omniedge needs to install Helper Tool to complete installation.")
25 | }
26 |
27 | self.connectToXPC()
28 | }
29 |
30 | func disconnect(){
31 | self.helperTool?.disconnect()
32 | XPCConnection?.invalidationHandler = nil
33 | XPCConnection?.interruptionHandler = nil
34 | self.XPCConnection = nil
35 | }
36 |
37 | func connect(dataOfNetworkConfig: Data, completed: @escaping (Bool, Error?) -> Void) {
38 | self.helperTool?.connect(dataOfNetworkConfig, completion: { err in
39 | completed(err == nil, err)
40 | })
41 | }
42 |
43 | private func connectToXPC(){
44 |
45 | self.XPCConnection = NSXPCConnection(machServiceName: XPCConstant.HelperMachLabel,
46 | options: .privileged)
47 |
48 | XPCConnection?.remoteObjectInterface = NSXPCInterface(with: HelperTool.self)
49 |
50 | XPCConnection?.invalidationHandler = connectionInvalidationHandler
51 | XPCConnection?.interruptionHandler = connetionInterruptionHandler
52 |
53 | XPCConnection?.resume()
54 |
55 | self.helperTool = XPCConnection?.remoteObjectProxy as? HelperTool
56 | // self.helperTool?.version(completion: checkHelperVersion)
57 | }
58 |
59 | private func checkHelperVersion(ver: String){
60 | if ver != XPCConstant.HelperToolVersion{
61 | DispatchQueue.main.async {
62 | self.alertInstall("Omniedge needs to upgrade Helper Tool.")
63 | }
64 | }
65 | }
66 |
67 |
68 | private func connetionInterruptionHandler() {
69 | NSLog("interrupted Connection")
70 |
71 | }
72 |
73 | private func connectionInvalidationHandler() {
74 | NSLog("Invalid Connection")
75 | }
76 |
77 | private func alertInstall(_ message: String){
78 | let alert = NSAlert()
79 | alert.alertStyle = .informational
80 | alert.messageText = message
81 | let okButton = alert.addButton(withTitle: "OK")
82 | alert.window.defaultButtonCell = okButton.cell as? NSButtonCell
83 | alert.addButton(withTitle: "Cancel")
84 | let modal = alert.runModal()
85 |
86 | switch modal {
87 | case .OK, .alertFirstButtonReturn:
88 | self.installHelperTool()
89 | default:
90 | self.notAbleToStart(nil)
91 | }
92 | }
93 |
94 |
95 | private func notAbleToStart(_ message: String?){
96 | let alert = NSAlert()
97 | alert.alertStyle = .critical
98 | alert.messageText = message ?? "Omniedge not able to start."
99 | alert.addButton(withTitle: "Exit")
100 | alert.runModal()
101 |
102 | NSRunningApplication.current.terminate()
103 | }
104 |
105 |
106 |
107 | private func installHelperTool(){
108 |
109 | self.disconnect()
110 | guard let auth = Utils.askAuthorization() else {
111 | fatalError("Authorization not acquired.")
112 | }
113 |
114 | if(!Utils.blessHelper(label: XPCConstant.HelperMachLabel, authorization: auth)){
115 | self.notAbleToStart("Install HelperTool failed.")
116 | }
117 |
118 | self.connectToXPC()
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/Sparkle.framework/Headers:
--------------------------------------------------------------------------------
1 | Versions/Current/Headers
--------------------------------------------------------------------------------
/Sparkle.framework/Modules:
--------------------------------------------------------------------------------
1 | Versions/Current/Modules
--------------------------------------------------------------------------------
/Sparkle.framework/PrivateHeaders:
--------------------------------------------------------------------------------
1 | Versions/Current/PrivateHeaders
--------------------------------------------------------------------------------
/Sparkle.framework/Resources:
--------------------------------------------------------------------------------
1 | Versions/Current/Resources
--------------------------------------------------------------------------------
/Sparkle.framework/Sparkle:
--------------------------------------------------------------------------------
1 | Versions/Current/Sparkle
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Headers/SPUDownloadData.h:
--------------------------------------------------------------------------------
1 | //
2 | // SPUDownloadData.h
3 | // Sparkle
4 | //
5 | // Created by Mayur Pawashe on 8/10/16.
6 | // Copyright © 2016 Sparkle Project. All rights reserved.
7 | //
8 |
9 | #if __has_feature(modules)
10 | @import Foundation;
11 | #else
12 | #import
13 | #endif
14 |
15 | #import "SUExport.h"
16 |
17 | NS_ASSUME_NONNULL_BEGIN
18 |
19 | /*!
20 | * A class for containing downloaded data along with some information about it.
21 | */
22 | SU_EXPORT @interface SPUDownloadData : NSObject
23 |
24 | - (instancetype)initWithData:(NSData *)data textEncodingName:(NSString * _Nullable)textEncodingName MIMEType:(NSString * _Nullable)MIMEType;
25 |
26 | /*!
27 | * The raw data that was downloaded.
28 | */
29 | @property (nonatomic, readonly) NSData *data;
30 |
31 | /*!
32 | * The IANA charset encoding name if available. Eg: "utf-8"
33 | */
34 | @property (nonatomic, readonly, nullable, copy) NSString *textEncodingName;
35 |
36 | /*!
37 | * The MIME type if available. Eg: "text/plain"
38 | */
39 | @property (nonatomic, readonly, nullable, copy) NSString *MIMEType;
40 |
41 | @end
42 |
43 | NS_ASSUME_NONNULL_END
44 |
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Headers/SPUDownloader.h:
--------------------------------------------------------------------------------
1 | //
2 | // SPUDownloader.h
3 | // Downloader
4 | //
5 | // Created by Mayur Pawashe on 4/1/16.
6 | // Copyright © 2016 Sparkle Project. All rights reserved.
7 | //
8 |
9 | #if __has_feature(modules)
10 | @import Foundation;
11 | #else
12 | #import
13 | #endif
14 | #import "SPUDownloaderProtocol.h"
15 |
16 | @protocol SPUDownloaderDelegate;
17 |
18 | // This object implements the protocol which we have defined. It provides the actual behavior for the service. It is 'exported' by the service to make it available to the process hosting the service over an NSXPCConnection.
19 | @interface SPUDownloader : NSObject
20 |
21 | // Due to XPC remote object reasons, this delegate is strongly referenced
22 | // Invoke cleanup when done with this instance
23 | - (instancetype)initWithDelegate:(id )delegate;
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Headers/SPUDownloaderDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // SPUDownloaderDelegate.h
3 | // Sparkle
4 | //
5 | // Created by Mayur Pawashe on 4/1/16.
6 | // Copyright © 2016 Sparkle Project. All rights reserved.
7 | //
8 |
9 | #if __has_feature(modules)
10 | @import Foundation;
11 | #else
12 | #import
13 | #endif
14 |
15 | NS_ASSUME_NONNULL_BEGIN
16 |
17 | @class SPUDownloadData;
18 |
19 | @protocol SPUDownloaderDelegate
20 |
21 | // This is only invoked for persistent downloads
22 | - (void)downloaderDidSetDestinationName:(NSString *)destinationName temporaryDirectory:(NSString *)temporaryDirectory;
23 |
24 | // Under rare cases, this may be called more than once, in which case the current progress should be reset back to 0
25 | // This is only invoked for persistent downloads
26 | - (void)downloaderDidReceiveExpectedContentLength:(int64_t)expectedContentLength;
27 |
28 | // This is only invoked for persistent downloads
29 | - (void)downloaderDidReceiveDataOfLength:(uint64_t)length;
30 |
31 | // downloadData is nil if this is a persisent download, otherwise it's non-nil if it's a temporary download
32 | - (void)downloaderDidFinishWithTemporaryDownloadData:(SPUDownloadData * _Nullable)downloadData;
33 |
34 | - (void)downloaderDidFailWithError:(NSError *)error;
35 |
36 | @end
37 |
38 | NS_ASSUME_NONNULL_END
39 |
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Headers/SPUDownloaderDeprecated.h:
--------------------------------------------------------------------------------
1 | //
2 | // SPUDownloaderDeprecated.h
3 | // Sparkle
4 | //
5 | // Created by Deadpikle on 12/20/17.
6 | // Copyright © 2017 Sparkle Project. All rights reserved.
7 | //
8 |
9 | #import "SPUDownloader.h"
10 |
11 | @interface SPUDownloaderDeprecated : SPUDownloader
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Headers/SPUDownloaderProtocol.h:
--------------------------------------------------------------------------------
1 | //
2 | // SPUDownloaderProtocol.h
3 | // PersistentDownloader
4 | //
5 | // Created by Mayur Pawashe on 4/1/16.
6 | // Copyright © 2016 Sparkle Project. All rights reserved.
7 | //
8 |
9 | #if __has_feature(modules)
10 | @import Foundation;
11 | #else
12 | #import
13 | #endif
14 |
15 | NS_ASSUME_NONNULL_BEGIN
16 |
17 | @class SPUURLRequest;
18 |
19 | // The protocol that this service will vend as its API. This header file will also need to be visible to the process hosting the service.
20 | @protocol SPUDownloaderProtocol
21 |
22 | - (void)startPersistentDownloadWithRequest:(SPUURLRequest *)request bundleIdentifier:(NSString *)bundleIdentifier desiredFilename:(NSString *)desiredFilename;
23 |
24 | - (void)startTemporaryDownloadWithRequest:(SPUURLRequest *)request;
25 |
26 | - (void)downloadDidFinish;
27 |
28 | - (void)cleanup;
29 |
30 | - (void)cancel;
31 |
32 | @end
33 |
34 | NS_ASSUME_NONNULL_END
35 |
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Headers/SPUDownloaderSession.h:
--------------------------------------------------------------------------------
1 | //
2 | // SPUDownloaderSession.h
3 | // Sparkle
4 | //
5 | // Created by Deadpikle on 12/20/17.
6 | // Copyright © 2017 Sparkle Project. All rights reserved.
7 | //
8 |
9 | #if __has_feature(modules)
10 | @import Foundation;
11 | #else
12 | #import
13 | #endif
14 | #import "SPUDownloader.h"
15 | #import "SPUDownloaderProtocol.h"
16 |
17 | NS_CLASS_AVAILABLE(NSURLSESSION_AVAILABLE, 7_0)
18 | @interface SPUDownloaderSession : SPUDownloader
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Headers/SPUURLRequest.h:
--------------------------------------------------------------------------------
1 | //
2 | // SPUURLRequest.h
3 | // Sparkle
4 | //
5 | // Created by Mayur Pawashe on 5/19/16.
6 | // Copyright © 2016 Sparkle Project. All rights reserved.
7 | //
8 |
9 | #if __has_feature(modules)
10 | @import Foundation;
11 | #else
12 | #import
13 | #endif
14 |
15 | NS_ASSUME_NONNULL_BEGIN
16 |
17 | // A class that wraps NSURLRequest and implements NSSecureCoding
18 | // This class exists because NSURLRequest did not support NSSecureCoding in macOS 10.8
19 | // I have not verified if NSURLRequest in 10.9 implements NSSecureCoding or not
20 | @interface SPUURLRequest : NSObject
21 |
22 | // Creates a new URL request
23 | // Only these properties are currently tracked:
24 | // * URL
25 | // * Cache policy
26 | // * Timeout interval
27 | // * HTTP header fields
28 | // * networkServiceType
29 | + (instancetype)URLRequestWithRequest:(NSURLRequest *)request;
30 |
31 | @property (nonatomic, readonly) NSURLRequest *request;
32 |
33 | @end
34 |
35 | NS_ASSUME_NONNULL_END
36 |
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Headers/SUAppcast.h:
--------------------------------------------------------------------------------
1 | //
2 | // SUAppcast.h
3 | // Sparkle
4 | //
5 | // Created by Andy Matuschak on 3/12/06.
6 | // Copyright 2006 Andy Matuschak. All rights reserved.
7 | //
8 |
9 | #ifndef SUAPPCAST_H
10 | #define SUAPPCAST_H
11 |
12 | #if __has_feature(modules)
13 | @import Foundation;
14 | #else
15 | #import
16 | #endif
17 | #import "SUExport.h"
18 |
19 | NS_ASSUME_NONNULL_BEGIN
20 |
21 | @class SUAppcastItem;
22 | SU_EXPORT @interface SUAppcast : NSObject
23 |
24 | @property (copy, nullable) NSString *userAgentString;
25 | @property (copy, nullable) NSDictionary *httpHeaders;
26 |
27 | - (void)fetchAppcastFromURL:(NSURL *)url inBackground:(BOOL)bg completionBlock:(void (^)(NSError *_Nullable))err;
28 | - (SUAppcast *)copyWithoutDeltaUpdates;
29 |
30 | @property (readonly, copy, nullable) NSArray *items;
31 | @end
32 |
33 | NS_ASSUME_NONNULL_END
34 |
35 | #endif
36 |
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Headers/SUAppcastItem.h:
--------------------------------------------------------------------------------
1 | //
2 | // SUAppcastItem.h
3 | // Sparkle
4 | //
5 | // Created by Andy Matuschak on 3/12/06.
6 | // Copyright 2006 Andy Matuschak. All rights reserved.
7 | //
8 |
9 | #ifndef SUAPPCASTITEM_H
10 | #define SUAPPCASTITEM_H
11 |
12 | #if __has_feature(modules)
13 | @import Foundation;
14 | #else
15 | #import
16 | #endif
17 | #import "SUExport.h"
18 | @class SUSignatures;
19 |
20 | SU_EXPORT @interface SUAppcastItem : NSObject
21 | @property (copy, readonly) NSString *title;
22 | @property (copy, readonly) NSString *dateString;
23 | @property (copy, readonly) NSDate *date;
24 | @property (copy, readonly) NSString *itemDescription;
25 | @property (strong, readonly) NSURL *releaseNotesURL;
26 | @property (strong, readonly) SUSignatures *signatures;
27 | @property (copy, readonly) NSString *minimumSystemVersion;
28 | @property (copy, readonly) NSString *maximumSystemVersion;
29 | @property (strong, readonly) NSURL *fileURL;
30 | @property (nonatomic, readonly) uint64_t contentLength;
31 | @property (copy, readonly) NSString *versionString;
32 | @property (copy, readonly) NSString *osString;
33 | @property (copy, readonly) NSString *displayVersionString;
34 | @property (copy, readonly) NSDictionary *deltaUpdates;
35 | @property (strong, readonly) NSURL *infoURL;
36 | @property (copy, readonly) NSNumber* phasedRolloutInterval;
37 |
38 | // Initializes with data from a dictionary provided by the RSS class.
39 | - (instancetype)initWithDictionary:(NSDictionary *)dict;
40 | - (instancetype)initWithDictionary:(NSDictionary *)dict failureReason:(NSString **)error;
41 |
42 | @property (getter=isDeltaUpdate, readonly) BOOL deltaUpdate;
43 | @property (getter=isCriticalUpdate, readonly) BOOL criticalUpdate;
44 | @property (getter=isMacOsUpdate, readonly) BOOL macOsUpdate;
45 | @property (getter=isInformationOnlyUpdate, readonly) BOOL informationOnlyUpdate;
46 |
47 | // Returns the dictionary provided in initWithDictionary; this might be useful later for extensions.
48 | @property (readonly, copy) NSDictionary *propertiesDictionary;
49 |
50 | - (NSURL *)infoURL;
51 |
52 | @end
53 |
54 | #endif
55 |
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Headers/SUCodeSigningVerifier.h:
--------------------------------------------------------------------------------
1 | //
2 | // SUCodeSigningVerifier.h
3 | // Sparkle
4 | //
5 | // Created by Andy Matuschak on 7/5/12.
6 | //
7 | //
8 |
9 | #ifndef SUCODESIGNINGVERIFIER_H
10 | #define SUCODESIGNINGVERIFIER_H
11 |
12 | #if __has_feature(modules)
13 | @import Foundation;
14 | #else
15 | #import
16 | #endif
17 | #import "SUExport.h"
18 |
19 | SU_EXPORT @interface SUCodeSigningVerifier : NSObject
20 | + (BOOL)codeSignatureAtBundleURL:(NSURL *)oldBundlePath matchesSignatureAtBundleURL:(NSURL *)newBundlePath error:(NSError **)error;
21 | + (BOOL)codeSignatureIsValidAtBundleURL:(NSURL *)bundlePath error:(NSError **)error;
22 | + (BOOL)bundleAtURLIsCodeSigned:(NSURL *)bundlePath;
23 | + (NSDictionary *)codeSignatureInfoAtBundleURL:(NSURL *)bundlePath;
24 | @end
25 |
26 | #endif
27 |
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Headers/SUErrors.h:
--------------------------------------------------------------------------------
1 | //
2 | // SUErrors.h
3 | // Sparkle
4 | //
5 | // Created by C.W. Betts on 10/13/14.
6 | // Copyright (c) 2014 Sparkle Project. All rights reserved.
7 | //
8 |
9 | #ifndef SUERRORS_H
10 | #define SUERRORS_H
11 |
12 | #if __has_feature(modules)
13 | @import Foundation;
14 | #else
15 | #import
16 | #endif
17 | #import "SUExport.h"
18 |
19 | /**
20 | * Error domain used by Sparkle
21 | */
22 | SU_EXPORT extern NSString *const SUSparkleErrorDomain;
23 |
24 | #pragma clang diagnostic push
25 | #pragma clang diagnostic ignored "-Wc++98-compat"
26 | typedef NS_ENUM(OSStatus, SUError) {
27 | // Appcast phase errors.
28 | SUAppcastParseError = 1000,
29 | SUNoUpdateError = 1001,
30 | SUAppcastError = 1002,
31 | SURunningFromDiskImageError = 1003,
32 | SURunningTranslocated = 1004,
33 |
34 | // Download phase errors.
35 | SUTemporaryDirectoryError = 2000,
36 | SUDownloadError = 2001,
37 |
38 | // Extraction phase errors.
39 | SUUnarchivingError = 3000,
40 | SUSignatureError = 3001,
41 |
42 | // Installation phase errors.
43 | SUFileCopyFailure = 4000,
44 | SUAuthenticationFailure = 4001,
45 | SUMissingUpdateError = 4002,
46 | SUMissingInstallerToolError = 4003,
47 | SURelaunchError = 4004,
48 | SUInstallationError = 4005,
49 | SUDowngradeError = 4006,
50 | SUInstallationCancelledError = 4007,
51 |
52 | // System phase errors
53 | SUSystemPowerOffError = 5000
54 | };
55 | #pragma clang diagnostic pop
56 |
57 | #endif
58 |
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Headers/SUExport.h:
--------------------------------------------------------------------------------
1 | //
2 | // SUExport.h
3 | // Sparkle
4 | //
5 | // Created by Jake Petroules on 2014-08-23.
6 | // Copyright (c) 2014 Sparkle Project. All rights reserved.
7 | //
8 |
9 | #ifndef SUEXPORT_H
10 | #define SUEXPORT_H
11 |
12 | #ifdef BUILDING_SPARKLE
13 | #define SU_EXPORT __attribute__((visibility("default")))
14 | #else
15 | #define SU_EXPORT
16 | #endif
17 |
18 | #endif
19 |
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Headers/SUStandardVersionComparator.h:
--------------------------------------------------------------------------------
1 | //
2 | // SUStandardVersionComparator.h
3 | // Sparkle
4 | //
5 | // Created by Andy Matuschak on 12/21/07.
6 | // Copyright 2007 Andy Matuschak. All rights reserved.
7 | //
8 |
9 | #ifndef SUSTANDARDVERSIONCOMPARATOR_H
10 | #define SUSTANDARDVERSIONCOMPARATOR_H
11 |
12 | #if __has_feature(modules)
13 | @import Foundation;
14 | #else
15 | #import
16 | #endif
17 | #import "SUExport.h"
18 | #import "SUVersionComparisonProtocol.h"
19 |
20 | NS_ASSUME_NONNULL_BEGIN
21 |
22 | /*!
23 | Sparkle's default version comparator.
24 |
25 | This comparator is adapted from MacPAD, by Kevin Ballard.
26 | It's "dumb" in that it does essentially string comparison,
27 | in components split by character type.
28 | */
29 | SU_EXPORT @interface SUStandardVersionComparator : NSObject
30 |
31 | /*!
32 | Initializes a new instance of the standard version comparator.
33 | */
34 | - (instancetype)init;
35 |
36 | /*!
37 | Returns a singleton instance of the comparator.
38 |
39 | It is usually preferred to alloc/init new a comparator instead.
40 | */
41 | + (SUStandardVersionComparator *)defaultComparator;
42 |
43 | /*!
44 | Compares version strings through textual analysis.
45 |
46 | See the implementation for more details.
47 | */
48 | - (NSComparisonResult)compareVersion:(NSString *)versionA toVersion:(NSString *)versionB;
49 | @end
50 |
51 | NS_ASSUME_NONNULL_END
52 | #endif
53 |
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Headers/SUUpdater.h:
--------------------------------------------------------------------------------
1 | //
2 | // SUUpdater.h
3 | // Sparkle
4 | //
5 | // Created by Andy Matuschak on 1/4/06.
6 | // Copyright 2006 Andy Matuschak. All rights reserved.
7 | //
8 |
9 | #ifndef SUUPDATER_H
10 | #define SUUPDATER_H
11 |
12 | #if __has_feature(modules)
13 | @import Cocoa;
14 | #else
15 | #import
16 | #endif
17 | #import "SUExport.h"
18 | #import "SUVersionComparisonProtocol.h"
19 | #import "SUVersionDisplayProtocol.h"
20 |
21 | @class SUAppcastItem, SUAppcast;
22 |
23 | @protocol SUUpdaterDelegate;
24 |
25 | /*!
26 | The main API in Sparkle for controlling the update mechanism.
27 |
28 | This class is used to configure the update paramters as well as manually
29 | and automatically schedule and control checks for updates.
30 | */
31 | SU_EXPORT @interface SUUpdater : NSObject
32 |
33 | @property (unsafe_unretained) IBOutlet id delegate;
34 |
35 | /*!
36 | The shared updater for the main bundle.
37 |
38 | This is equivalent to passing [NSBundle mainBundle] to SUUpdater::updaterForBundle:
39 | */
40 | + (SUUpdater *)sharedUpdater;
41 |
42 | /*!
43 | The shared updater for a specified bundle.
44 |
45 | If an updater has already been initialized for the provided bundle, that shared instance will be returned.
46 | */
47 | + (SUUpdater *)updaterForBundle:(NSBundle *)bundle;
48 |
49 | /*!
50 | Designated initializer for SUUpdater.
51 |
52 | If an updater has already been initialized for the provided bundle, that shared instance will be returned.
53 | */
54 | - (instancetype)initForBundle:(NSBundle *)bundle;
55 |
56 | /*!
57 | Explicitly checks for updates and displays a progress dialog while doing so.
58 |
59 | This method is meant for a main menu item.
60 | Connect any menu item to this action in Interface Builder,
61 | and Sparkle will check for updates and report back its findings verbosely
62 | when it is invoked.
63 |
64 | This will find updates that the user has opted into skipping.
65 | */
66 | - (IBAction)checkForUpdates:(id)sender;
67 |
68 | /*!
69 | The menu item validation used for the -checkForUpdates: action
70 | */
71 | - (BOOL)validateMenuItem:(NSMenuItem *)menuItem;
72 |
73 | /*!
74 | Checks for updates, but does not display any UI unless an update is found.
75 |
76 | This is meant for programmatically initating a check for updates. That is,
77 | it will display no UI unless it actually finds an update, in which case it
78 | proceeds as usual.
79 |
80 | If automatic downloading of updates it turned on and allowed, however,
81 | this will invoke that behavior, and if an update is found, it will be downloaded
82 | in the background silently and will be prepped for installation.
83 |
84 | This will not find updates that the user has opted into skipping.
85 | */
86 | - (void)checkForUpdatesInBackground;
87 |
88 | /*!
89 | A property indicating whether or not to check for updates automatically.
90 |
91 | Setting this property will persist in the host bundle's user defaults.
92 | The update schedule cycle will be reset in a short delay after the property's new value is set.
93 | This is to allow reverting this property without kicking off a schedule change immediately
94 | */
95 | @property BOOL automaticallyChecksForUpdates;
96 |
97 | /*!
98 | A property indicating whether or not updates can be automatically downloaded in the background.
99 |
100 | Note that automatic downloading of updates can be disallowed by the developer
101 | or by the user's system if silent updates cannot be done (eg: if they require authentication).
102 | In this case, -automaticallyDownloadsUpdates will return NO regardless of how this property is set.
103 |
104 | Setting this property will persist in the host bundle's user defaults.
105 | */
106 | @property BOOL automaticallyDownloadsUpdates;
107 |
108 | /*!
109 | A property indicating the current automatic update check interval.
110 |
111 | Setting this property will persist in the host bundle's user defaults.
112 | The update schedule cycle will be reset in a short delay after the property's new value is set.
113 | This is to allow reverting this property without kicking off a schedule change immediately
114 | */
115 | @property NSTimeInterval updateCheckInterval;
116 |
117 | /*!
118 | Begins a "probing" check for updates which will not actually offer to
119 | update to that version.
120 |
121 | However, the delegate methods
122 | SUUpdaterDelegate::updater:didFindValidUpdate: and
123 | SUUpdaterDelegate::updaterDidNotFindUpdate: will be called,
124 | so you can use that information in your UI.
125 |
126 | Updates that have been skipped by the user will not be found.
127 | */
128 | - (void)checkForUpdateInformation;
129 |
130 | /*!
131 | The URL of the appcast used to download update information.
132 |
133 | Setting this property will persist in the host bundle's user defaults.
134 | If you don't want persistence, you may want to consider instead implementing
135 | SUUpdaterDelegate::feedURLStringForUpdater: or SUUpdaterDelegate::feedParametersForUpdater:sendingSystemProfile:
136 |
137 | This property must be called on the main thread.
138 | */
139 | @property (copy) NSURL *feedURL;
140 |
141 | /*!
142 | The host bundle that is being updated.
143 | */
144 | @property (readonly, strong) NSBundle *hostBundle;
145 |
146 | /*!
147 | The bundle this class (SUUpdater) is loaded into.
148 | */
149 | @property (strong, readonly) NSBundle *sparkleBundle;
150 |
151 | /*!
152 | The user agent used when checking for updates.
153 |
154 | The default implementation can be overrided.
155 | */
156 | @property (nonatomic, copy) NSString *userAgentString;
157 |
158 | /*!
159 | The HTTP headers used when checking for updates.
160 |
161 | The keys of this dictionary are HTTP header fields (NSString) and values are corresponding values (NSString)
162 | */
163 | @property (copy) NSDictionary *httpHeaders;
164 |
165 | /*!
166 | A property indicating whether or not the user's system profile information is sent when checking for updates.
167 |
168 | Setting this property will persist in the host bundle's user defaults.
169 | */
170 | @property BOOL sendsSystemProfile;
171 |
172 | /*!
173 | A property indicating the decryption password used for extracting updates shipped as Apple Disk Images (dmg)
174 | */
175 | @property (nonatomic, copy) NSString *decryptionPassword;
176 |
177 | /*!
178 | This function ignores normal update schedule, ignores user preferences,
179 | and interrupts users with an unwanted immediate app update.
180 |
181 | WARNING: this function should not be used in regular apps. This function
182 | is a user-unfriendly hack only for very special cases, like unstable
183 | rapidly-changing beta builds that would not run correctly if they were
184 | even one day out of date.
185 |
186 | Instead of this function you should set `SUAutomaticallyUpdate` to `YES`,
187 | which will gracefully install updates when the app quits.
188 |
189 | For UI-less/daemon apps that aren't usually quit, instead of this function,
190 | you can use the delegate method
191 | SUUpdaterDelegate::updater:willInstallUpdateOnQuit:immediateInstallationInvocation:
192 | or
193 | SUUpdaterDelegate::updater:willInstallUpdateOnQuit:immediateInstallationBlock:
194 | to immediately start installation when an update was found.
195 |
196 | A progress dialog is shown but the user will never be prompted to read the
197 | release notes.
198 |
199 | This function will cause update to be downloaded twice if automatic updates are
200 | enabled.
201 |
202 | You may want to respond to the userDidCancelDownload delegate method in case
203 | the user clicks the "Cancel" button while the update is downloading.
204 | */
205 | - (void)installUpdatesIfAvailable;
206 |
207 | /*!
208 | Returns the date of last update check.
209 |
210 | \returns \c nil if no check has been performed.
211 | */
212 | @property (readonly, copy) NSDate *lastUpdateCheckDate;
213 |
214 | /*!
215 | Appropriately schedules or cancels the update checking timer according to
216 | the preferences for time interval and automatic checks.
217 |
218 | This call does not change the date of the next check,
219 | but only the internal NSTimer.
220 | */
221 | - (void)resetUpdateCycle;
222 |
223 | /*!
224 | A property indicating whether or not an update is in progress.
225 |
226 | Note this property is not indicative of whether or not user initiated updates can be performed.
227 | Use SUUpdater::validateMenuItem: for that instead.
228 | */
229 | @property (readonly) BOOL updateInProgress;
230 |
231 | @end
232 |
233 | #endif
234 |
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Headers/SUVersionComparisonProtocol.h:
--------------------------------------------------------------------------------
1 | //
2 | // SUVersionComparisonProtocol.h
3 | // Sparkle
4 | //
5 | // Created by Andy Matuschak on 12/21/07.
6 | // Copyright 2007 Andy Matuschak. All rights reserved.
7 | //
8 |
9 | #ifndef SUVERSIONCOMPARISONPROTOCOL_H
10 | #define SUVERSIONCOMPARISONPROTOCOL_H
11 |
12 | #if __has_feature(modules)
13 | @import Foundation;
14 | #else
15 | #import
16 | #endif
17 | #import "SUExport.h"
18 |
19 | NS_ASSUME_NONNULL_BEGIN
20 |
21 | /*!
22 | Provides version comparison facilities for Sparkle.
23 | */
24 | @protocol SUVersionComparison
25 |
26 | /*!
27 | An abstract method to compare two version strings.
28 |
29 | Should return NSOrderedAscending if b > a, NSOrderedDescending if b < a,
30 | and NSOrderedSame if they are equivalent.
31 | */
32 | - (NSComparisonResult)compareVersion:(NSString *)versionA toVersion:(NSString *)versionB; // *** MAY BE CALLED ON NON-MAIN THREAD!
33 |
34 | @end
35 |
36 | NS_ASSUME_NONNULL_END
37 | #endif
38 |
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Headers/SUVersionDisplayProtocol.h:
--------------------------------------------------------------------------------
1 | //
2 | // SUVersionDisplayProtocol.h
3 | // EyeTV
4 | //
5 | // Created by Uli Kusterer on 08.12.09.
6 | // Copyright 2009 Elgato Systems GmbH. All rights reserved.
7 | //
8 |
9 | #if __has_feature(modules)
10 | @import Foundation;
11 | #else
12 | #import
13 | #endif
14 | #import "SUExport.h"
15 |
16 | /*!
17 | Applies special display formatting to version numbers.
18 | */
19 | @protocol SUVersionDisplay
20 |
21 | /*!
22 | Formats two version strings.
23 |
24 | Both versions are provided so that important distinguishing information
25 | can be displayed while also leaving out unnecessary/confusing parts.
26 | */
27 | - (void)formatVersion:(NSString *_Nonnull*_Nonnull)inOutVersionA andVersion:(NSString *_Nonnull*_Nonnull)inOutVersionB;
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Headers/Sparkle.h:
--------------------------------------------------------------------------------
1 | //
2 | // Sparkle.h
3 | // Sparkle
4 | //
5 | // Created by Andy Matuschak on 3/16/06. (Modified by CDHW on 23/12/07)
6 | // Copyright 2006 Andy Matuschak. All rights reserved.
7 | //
8 |
9 | #ifndef SPARKLE_H
10 | #define SPARKLE_H
11 |
12 | // This list should include the shared headers. It doesn't matter if some of them aren't shared (unless
13 | // there are name-space collisions) so we can list all of them to start with:
14 |
15 | #pragma clang diagnostic push
16 | // Do not use <> style includes since 2.x has two frameworks that need to work: Sparkle and SparkleCore
17 | #pragma clang diagnostic ignored "-Wquoted-include-in-framework-header"
18 |
19 | #import "SUAppcast.h"
20 | #import "SUAppcastItem.h"
21 | #import "SUStandardVersionComparator.h"
22 | #import "SUUpdater.h"
23 | #import "SUUpdaterDelegate.h"
24 | #import "SUVersionComparisonProtocol.h"
25 | #import "SUVersionDisplayProtocol.h"
26 | #import "SUErrors.h"
27 |
28 | #import "SPUDownloader.h"
29 | #import "SPUDownloaderDelegate.h"
30 | #import "SPUDownloaderDeprecated.h"
31 | #import "SPUDownloadData.h"
32 | #import "SPUDownloaderProtocol.h"
33 | #import "SPUDownloaderSession.h"
34 | #import "SPUURLRequest.h"
35 | #import "SUCodeSigningVerifier.h"
36 |
37 | #pragma clang diagnostic pop
38 |
39 | #endif
40 |
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Modules/module.modulemap:
--------------------------------------------------------------------------------
1 | framework module Sparkle {
2 | umbrella header "Sparkle.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/PrivateHeaders/SUUnarchiver.h:
--------------------------------------------------------------------------------
1 | //
2 | // SUUnarchiver.h
3 | // Sparkle
4 | //
5 | // Created by Andy Matuschak on 3/16/06.
6 | // Copyright 2006 Andy Matuschak. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @protocol SUUnarchiverProtocol;
14 |
15 | @interface SUUnarchiver : NSObject
16 |
17 | + (nullable id )unarchiverForPath:(NSString *)path updatingHostBundlePath:(nullable NSString *)hostPath decryptionPassword:(nullable NSString *)decryptionPassword;
18 |
19 | @end
20 |
21 | NS_ASSUME_NONNULL_END
22 |
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/DarkAqua.css:
--------------------------------------------------------------------------------
1 | html {
2 | color: #FFFFFFD8;
3 | }
4 | :link {
5 | color: #419CFF;
6 | }
7 | :link:active {
8 | color: #FF1919;
9 | }
10 |
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildMachineOSBuild
6 | 20B28
7 | CFBundleDevelopmentRegion
8 | en
9 | CFBundleExecutable
10 | Sparkle
11 | CFBundleIdentifier
12 | org.sparkle-project.Sparkle
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | Sparkle
17 | CFBundlePackageType
18 | FMWK
19 | CFBundleShortVersionString
20 | 1.24.0 a-67-g0e162c98
21 | CFBundleSignature
22 | ????
23 | CFBundleSupportedPlatforms
24 |
25 | MacOSX
26 |
27 | CFBundleVersion
28 | 1.24.0
29 | DTCompiler
30 | com.apple.compilers.llvm.clang.1_0
31 | DTPlatformBuild
32 | 12C5020f
33 | DTPlatformName
34 | macosx
35 | DTPlatformVersion
36 | 11.1
37 | DTSDKBuild
38 | 20C5048g
39 | DTSDKName
40 | macosx11.1
41 | DTXcode
42 | 1230
43 | DTXcodeBuild
44 | 12C5020f
45 | LSMinimumSystemVersion
46 | 10.7
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/SUStatus.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/SUStatus.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/ar.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/ar.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/ar.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/ar.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/ar.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/ar.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/ar.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/ar.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/ca.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/ca.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/cs.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/cs.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/cs.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/cs.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/cs.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/cs.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/cs.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/cs.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/da.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/da.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/da.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/da.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/da.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/da.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/da.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/da.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/de.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/de.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/de.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/de.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/el.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/el.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/el.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/el.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/el.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/el.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/el.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/el.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/en.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/en.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/es.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/es.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/es.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/es.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/fi.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/fi.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/fi.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/fi.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/fi.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/fi.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/fi.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/fi.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/fr.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/fr.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/fr.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/fr.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/fr_CA.lproj:
--------------------------------------------------------------------------------
1 | fr.lproj
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/he.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/he.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/hr.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/hr.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/hr.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/hr.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/hr.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/hr.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/hr.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/hr.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/hu.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/hu.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/hu.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/hu.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/hu.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/hu.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/hu.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/hu.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/is.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/is.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/is.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/is.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/is.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/is.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/is.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/is.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/it.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/it.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/it.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/it.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/ja.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/ja.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/ja.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/ja.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/ja.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/ja.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/ja.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/ja.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/ko.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/ko.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/ko.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/ko.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/ko.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/ko.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/ko.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/ko.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/nb.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/nb.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/nb.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/nb.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/nb.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/nb.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/nb.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/nb.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/nl.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/nl.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/nl.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/nl.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/pl.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/pl.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/pl.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/pl.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/pl.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/pl.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/pl.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/pl.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/pt.lproj:
--------------------------------------------------------------------------------
1 | pt_BR.lproj
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/ro.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/ro.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/ro.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/ro.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/ro.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/ro.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/ro.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/ro.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/ru.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/ru.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/ru.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/ru.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/sk.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/sk.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/sk.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/sk.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/sk.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/sk.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/sk.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/sk.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/sl.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/sl.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/sl.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/sl.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/sl.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/sl.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/sl.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/sl.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/sv.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/sv.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/sv.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/sv.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/th.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/th.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/th.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/th.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/th.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/th.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/th.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/th.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/tr.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/tr.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/tr.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/tr.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/tr.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/tr.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/tr.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/tr.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/uk.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/uk.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/uk.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/uk.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/uk.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/uk.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/uk.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/uk.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUAutomaticUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUAutomaticUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUUpdateAlert.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUUpdateAlert.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUUpdatePermissionPrompt.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUUpdatePermissionPrompt.nib
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/Sparkle.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/Sparkle.strings
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/A/Sparkle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omniedgeio/omniedge-macOS/41bb24888fb1a76eda6396d17dadf024ddcd61cf/Sparkle.framework/Versions/A/Sparkle
--------------------------------------------------------------------------------
/Sparkle.framework/Versions/Current:
--------------------------------------------------------------------------------
1 | A
--------------------------------------------------------------------------------
/Utils/OmError.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OmError.swift
3 | // Omniedge
4 | //
5 | // Created by Yanbo Dang on 12/8/2022.
6 | //
7 |
8 | import Foundation
9 |
10 | enum OmError: Error {
11 | case invalidRsp
12 | case invalidUrl
13 | case errCode(Int, String)
14 | case other(Error)
15 | }
16 |
--------------------------------------------------------------------------------
/Utils/Utils.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Utils.swift
3 | // Omniedge
4 | //
5 | // Created by Yanbo Dang on 16/7/2022.
6 | //
7 |
8 | import Foundation
9 | import ServiceManagement
10 | import AppKit
11 |
12 | class Utils {
13 |
14 | static func fromHex(hex: String) -> CGColor? {
15 | var hexSanitized = hex.trimmingCharacters(in: .whitespacesAndNewlines)
16 | hexSanitized = hexSanitized.replacingOccurrences(of: "#", with: "")
17 |
18 | var rgb: UInt64 = 0
19 |
20 | var r: CGFloat = 0.0
21 | var g: CGFloat = 0.0
22 | var b: CGFloat = 0.0
23 | var a: CGFloat = 1.0
24 |
25 | let length = hexSanitized.count
26 |
27 | guard Scanner(string: hexSanitized).scanHexInt64(&rgb) else { return nil }
28 |
29 | if length == 6 {
30 | r = CGFloat((rgb & 0xFF0000) >> 16) / 255.0
31 | g = CGFloat((rgb & 0x00FF00) >> 8) / 255.0
32 | b = CGFloat(rgb & 0x0000FF) / 255.0
33 |
34 | } else if length == 8 {
35 | r = CGFloat((rgb & 0xFF000000) >> 24) / 255.0
36 | g = CGFloat((rgb & 0x00FF0000) >> 16) / 255.0
37 | b = CGFloat((rgb & 0x0000FF00) >> 8) / 255.0
38 | a = CGFloat(rgb & 0x000000FF) / 255.0
39 |
40 | } else {
41 | return nil
42 | }
43 |
44 | return CGColor(red: r, green: g, blue: b, alpha: a)
45 | }
46 |
47 | @discardableResult
48 | static func blessHelper(label: String, authorization: AuthorizationRef) -> Bool {
49 |
50 | var error: Unmanaged?
51 | let blessStatus = SMJobBless(kSMDomainSystemLaunchd, label as CFString, authorization, &error)
52 |
53 | if !blessStatus {
54 | NSLog("[SMJBS]: Helper bless failed with error \(error!.takeUnretainedValue())")
55 |
56 | }
57 |
58 | return blessStatus
59 | }
60 |
61 | static func askAuthorization() -> AuthorizationRef? {
62 |
63 | var auth: AuthorizationRef?
64 | let status: OSStatus = AuthorizationCreate(nil, nil, [], &auth)
65 | if status != errAuthorizationSuccess {
66 | NSLog("[SMJBS]: Authorization failed with status code \(status)")
67 |
68 | return nil
69 | }
70 |
71 | return auth
72 | }
73 |
74 | static func alert(title: String, description: String, _ style: NSAlert.Style) {
75 | DispatchQueue.main.async {
76 | let alert = NSAlert()
77 | alert.messageText = title
78 | alert.informativeText = description
79 | alert.alertStyle = style
80 | alert.addButton(withTitle: "OK")
81 | alert.runModal()
82 | }
83 | }
84 |
85 | static func findEthernetInterfaces() -> io_iterator_t? {
86 |
87 | let matchingDict = IOServiceMatching("IOEthernetInterface") as NSMutableDictionary
88 | matchingDict["IOPropertyMatch"] = [ "IOPrimaryInterface" : true]
89 |
90 | var matchingServices : io_iterator_t = 0
91 | if IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &matchingServices) != KERN_SUCCESS {
92 | return nil
93 | }
94 |
95 | return matchingServices
96 | }
97 |
98 | static func getMACAddress(_ intfIterator : io_iterator_t) -> [UInt8]? {
99 |
100 | var macAddress : [UInt8]?
101 |
102 | var intfService = IOIteratorNext(intfIterator)
103 | while intfService != 0 {
104 |
105 | var controllerService : io_object_t = 0
106 | if IORegistryEntryGetParentEntry(intfService, "IOService", &controllerService) == KERN_SUCCESS {
107 |
108 | let dataUM = IORegistryEntryCreateCFProperty(controllerService, "IOMACAddress" as CFString, kCFAllocatorDefault, 0)
109 | if let data = dataUM?.takeRetainedValue() as? NSData {
110 | macAddress = [0, 0, 0, 0, 0, 0]
111 | data.getBytes(&macAddress!, length: macAddress!.count)
112 | }
113 | IOObjectRelease(controllerService)
114 | }
115 |
116 | IOObjectRelease(intfService)
117 | intfService = IOIteratorNext(intfIterator)
118 | }
119 |
120 | return macAddress
121 | }
122 |
123 | static func getDeviceInfo() -> DeviceModel? {
124 | let deviceName = ProcessInfo.processInfo.hostName
125 | // let osVersion = ProcessInfo.processInfo.operatingSystemVersionString
126 | guard let hardwareUUID = self.getHardwareUUID() else {
127 | return nil
128 | }
129 |
130 | return DeviceModel(deviceName: deviceName, deviceUuid: hardwareUUID, deviceOS: "macOS")
131 | }
132 |
133 | static func getHardwareUUID() -> String? {
134 | let dev = IOServiceMatching("IOPlatformExpertDevice")
135 | let platformExpert: io_service_t = IOServiceGetMatchingService(kIOMasterPortDefault, dev)
136 | let serialNumberAsCFString = IORegistryEntryCreateCFProperty(platformExpert, kIOPlatformUUIDKey as CFString, kCFAllocatorDefault, 0)
137 | IOObjectRelease(platformExpert)
138 | let ser: CFTypeRef? = serialNumberAsCFString?.takeUnretainedValue()
139 |
140 | guard let result = ser as? String else {
141 | return nil
142 | }
143 |
144 | return result
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/Views/BaseView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BaseView.swift
3 | // Omniedge
4 | //
5 | // Created by Yanbo Dang on 19/7/2022.
6 | //
7 |
8 | import Foundation
9 | import AppKit
10 |
11 | class BaseView: NSView {
12 |
13 | init() {
14 | super.init(frame: .zero)
15 | }
16 |
17 | @available(*, unavailable)
18 | required init?(coder: NSCoder) {
19 | fatalError("init(coder:) has not been implemented")
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Views/NetworkItemDetailView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NetworkItemDetailView.swift
3 | // Omniedge
4 | //
5 | // Created by Yanbo Dang on 20/7/2022.
6 | //
7 |
8 | import Foundation
9 | import OGSwitch
10 |
11 | protocol NetworItemDetailViewDelegate: AnyObject {
12 | func didToggled(on: Bool);
13 | }
14 |
15 | class NetworkItemDetailView: BaseView {
16 | weak public var delegate: NetworItemDetailViewDelegate?
17 |
18 | private var seperatorBottomCopnstraint: NSLayoutConstraint?
19 | private var model: VirtualNetworkModel
20 | private var deviceItemViews: [OmniLabel] = []
21 | private var enableConnection: Bool = true
22 |
23 | init(model: VirtualNetworkModel, enableConnection: Bool) {
24 | self.model = model
25 | self.enableConnection = enableConnection
26 | super.init()
27 | self.initView()
28 | self.initLayout()
29 | }
30 |
31 | func toggleOff() {
32 | self.connSwitch.setOn(isOn: false, animated: true)
33 | }
34 |
35 | func toggleOn() {
36 | self.connSwitch.setOn(isOn: true, animated: true)
37 | }
38 |
39 | private func initView() {
40 | self.translatesAutoresizingMaskIntoConstraints = false
41 | self.addSubview(self.deviceListTitle)
42 | self.addSubview(self.connSwitch)
43 | self.addSubview(self.seperator)
44 | self.createDeviceItemView()
45 | self.connSwitch.isHidden = !self.enableConnection
46 | }
47 |
48 | private func initLayout() {
49 | NSLayoutConstraint.activate([
50 | self.connSwitch.topAnchor.constraint(equalTo: self.topAnchor, constant: Constants.Margins.margin5),
51 | self.connSwitch.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -Constants.Margins.margin5),
52 | self.connSwitch.widthAnchor.constraint(equalToConstant: 40),
53 | self.connSwitch.heightAnchor.constraint(equalToConstant: 20),
54 |
55 | self.deviceListTitle.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: Constants.Margins.margin5),
56 | self.deviceListTitle.topAnchor.constraint(equalTo: self.topAnchor, constant: Constants.Margins.margin5),
57 | self.deviceListTitle.trailingAnchor.constraint(equalTo: self.connSwitch.leadingAnchor, constant: Constants.Margins.margin5),
58 |
59 | self.seperator.leadingAnchor.constraint(equalTo: self.leadingAnchor),
60 | self.seperator.trailingAnchor.constraint(equalTo: self.trailingAnchor),
61 | self.seperator.topAnchor.constraint(equalTo: self.connSwitch.bottomAnchor, constant: Constants.Margins.margin5),
62 | self.seperator.heightAnchor.constraint(equalToConstant: 1.0),
63 |
64 | self.widthAnchor.constraint(equalToConstant: 290)
65 | ])
66 |
67 | self.layoutDeviceItemViews()
68 | }
69 |
70 | private func createDeviceItemView() {
71 | self.model.devices?.forEach { device in
72 | let view = OmniLabel()
73 | view.translatesAutoresizingMaskIntoConstraints = false
74 | view.stringValue = "\(device.deviceName) \(device.virtualIp ?? String.Empty)"
75 | self.deviceItemViews.append(view)
76 | self.addSubview(view)
77 | }
78 | }
79 |
80 | private func layoutDeviceItemViews() {
81 | if self.deviceItemViews.count == 0 {
82 | self.seperatorBottomCopnstraint = self.seperator.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -10)
83 | self.seperatorBottomCopnstraint?.isActive = true
84 | return
85 | }
86 |
87 | var previousView: NSView = self.seperator
88 | self.deviceItemViews.forEach { itemView in
89 | NSLayoutConstraint.activate([
90 | itemView.leadingAnchor.constraint(equalTo: self.deviceListTitle.leadingAnchor),
91 | itemView.trailingAnchor.constraint(equalTo: self.deviceListTitle.trailingAnchor),
92 | itemView.topAnchor.constraint(equalTo: previousView.bottomAnchor, constant: Constants.Margins.margin10),
93 | ])
94 |
95 | previousView = itemView
96 | }
97 |
98 | self.deviceItemViews.last?.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -Constants.Margins.margin10).isActive = true
99 | }
100 |
101 | @objc private func didToggled() {
102 | self.delegate?.didToggled(on: self.connSwitch.isOn)
103 | }
104 |
105 | // Lazy loading
106 | private lazy var deviceListTitle: OmniLabel = {
107 | let view = OmniLabel()
108 | view.stringValue = "Devices of " + model.vnName
109 | view.translatesAutoresizingMaskIntoConstraints = false
110 | return view
111 | }()
112 |
113 | private lazy var connSwitch: OGSwitch = {
114 | let view = OGSwitch()
115 | view.target = self
116 | view.action = #selector(didToggled)
117 | view.translatesAutoresizingMaskIntoConstraints = false
118 | return view
119 | }()
120 |
121 | private lazy var seperator: NSView = {
122 | let view = NSView()
123 | view.wantsLayer = true
124 | view.layer?.backgroundColor = NSColor.lightGray.cgColor
125 | view.translatesAutoresizingMaskIntoConstraints = false
126 | return view
127 | }()
128 | }
129 |
--------------------------------------------------------------------------------
/Views/NetworkItemView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NetworkItemView.swift
3 | // Omniedge
4 | //
5 | // Created by Yanbo Dang on 19/7/2022.
6 | //
7 |
8 | import Foundation
9 | import AppKit
10 |
11 | class NetworkItemView: BaseView {
12 |
13 | private var isMouseOver: Bool = false {
14 | didSet {
15 | self.backgroundColor = isMouseOver ? .blue : .clear
16 | }
17 | }
18 |
19 | private var backgroundColor: NSColor? {
20 | didSet {
21 | self.setNeedsDisplay(self.bounds)
22 | }
23 | }
24 |
25 | private var didAddTrackingArea: Bool = false
26 |
27 | override init() {
28 | super.init()
29 | self.initView()
30 | self.initLayout()
31 | }
32 |
33 | convenience init(title: String) {
34 | self.init()
35 | self.titleLabel.stringValue = title
36 | }
37 |
38 | private func initView() {
39 | self.addSubview(self.titleLabel)
40 | self.addSubview(self.detailIndicator)
41 | }
42 |
43 | private func initLayout() {
44 | NSLayoutConstraint.activate([
45 | self.titleLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor),
46 | self.titleLabel.trailingAnchor.constraint(equalTo: self.detailIndicator.leadingAnchor, constant: -Constants.Margins.margin10),
47 | self.titleLabel.topAnchor.constraint(equalTo: self.topAnchor, constant: Constants.Margins.margin5),
48 | self.titleLabel.bottomAnchor.constraint(equalTo:self.bottomAnchor, constant: -Constants.Margins.margin5),
49 |
50 | self.detailIndicator.trailingAnchor.constraint(equalTo: self.trailingAnchor),
51 | self.detailIndicator.centerYAnchor.constraint(equalTo: self.titleLabel.centerYAnchor),
52 | self.detailIndicator.widthAnchor.constraint(equalTo: self.detailIndicator.heightAnchor)
53 | ])
54 |
55 | self.detailIndicator.setContentHuggingPriority(.defaultHigh + 1, for: .horizontal)
56 | self.detailIndicator.setContentCompressionResistancePriority(.defaultLow + 1, for: .horizontal)
57 | }
58 |
59 | @objc private func didTitleLabelClicked() {
60 | return
61 | }
62 |
63 | // override func updateTrackingAreas() {
64 | // var trackingAreas = self.trackingAreas
65 | // trackingAreas.removeAll()
66 | // print(self.bounds)
67 | // let hoverArea = NSTrackingArea(rect: self.bounds, options: [.mouseEnteredAndExited, .mouseMoved, .activeInActiveApp, .inVisibleRect, .assumeInside, .cursorUpdate], owner: self, userInfo: nil)
68 | // self.addTrackingArea(hoverArea)
69 | // }
70 | //
71 | // override func mouseEntered(with event: NSEvent) {
72 | // self.isMouseOver = true
73 | // }
74 | //
75 | // override func mouseExited(with event: NSEvent) {
76 | // self.isMouseOver = false
77 | // }
78 |
79 | private lazy var titleLabel: OmniLabel = {
80 | let view = OmniLabel()
81 | view.font = NSFont.systemFont(ofSize: 14)
82 | view.translatesAutoresizingMaskIntoConstraints = false
83 | view.addClick(target: self, action: #selector(didTitleLabelClicked))
84 | return view
85 | }()
86 |
87 | private lazy var detailIndicator: OmniLabel = {
88 | let view = OmniLabel()
89 | view.translatesAutoresizingMaskIntoConstraints = false
90 | view.stringValue = "〉"
91 | return view
92 | }()
93 | }
94 |
--------------------------------------------------------------------------------
/Views/OmniButtonCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OmniButtonCell.swift
3 | // Omniedge
4 | //
5 | // Created by Yanbo Dang on 19/7/2022.
6 | //
7 |
8 | import Foundation
9 | import AppKit
10 |
11 | // https://gist.github.com/marteinn/fa9301ad349b755da2e6
12 | class OmniButtonCell: NSButtonCell {
13 |
14 | // - (NSRect)titleRectForBounds:(NSRect)theRect {
15 | // NSRect titleFrame = [super titleRectForBounds:theRect];
16 | // NSSize titleSize = [[self attributedStringValue] size];
17 | //
18 | // titleFrame.origin.y = theRect.origin.y-(theRect.size.height-titleSize.height)*0.5;
19 | //
20 | // return titleFrame;
21 | // }
22 |
23 | override func titleRect(forBounds rect: NSRect) -> NSRect {
24 | var titleFrame = super.titleRect(forBounds: rect)
25 | titleFrame.origin.x = 0
26 |
27 | return titleFrame
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Views/OmniLabel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OmniLabel.swift
3 | // Omniedge
4 | //
5 | // Created by Yanbo Dang on 16/7/2022.
6 | //
7 |
8 | import Foundation
9 | import AppKit
10 |
11 | class OmniLabel: NSTextField {
12 |
13 | private var clickGesture: NSClickGestureRecognizer
14 |
15 | init() {
16 | self.clickGesture = NSClickGestureRecognizer()
17 | super.init(frame: .zero)
18 | self.initLabel()
19 | }
20 |
21 | required init?(coder: NSCoder) {
22 | fatalError("init(coder:) has not been implemented")
23 | }
24 |
25 | func addClick(target: AnyObject, action: Selector) {
26 | self.clickGesture.target = target
27 | self.clickGesture.action = action
28 | }
29 |
30 | private func initLabel() {
31 | self.usesSingleLineMode = false
32 | self.isEditable = false
33 | self.isBezeled = false
34 | self.alignment = .left
35 | self.translatesAutoresizingMaskIntoConstraints = false
36 | self.backgroundColor = .clear
37 | self.addGestureRecognizer(self.clickGesture)
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/appdmg.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Omniedge",
3 | "icon": "",
4 | "background": "",
5 | "contents": [
6 | { "x": 448, "y": 344, "type": "link", "path": "/Applications" },
7 | { "x": 192, "y": 344, "type": "file", "path": "/Users/yanbodang/Desktop/Omniedge/Products/Applications/Omniedge.app" }
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/uninstall.sh:
--------------------------------------------------------------------------------
1 | PRIVILEGED_HELPER_LABEL=io.omniedge.mac.Omniedge.HelperTool
2 |
3 | sudo rm /Library/PrivilegedHelperTools/$PRIVILEGED_HELPER_LABEL
4 | sudo rm /Library/LaunchDaemons/$PRIVILEGED_HELPER_LABEL.plist
5 | sudo launchctl bootout system/$PRIVILEGED_HELPER_LABEL #'Boot-out failed: 36: Operation now in progress' is OK output
6 |
7 | echo "Querying launchd..."
8 | LAUNCHD_OUTPUT=$(sudo launchctl list | grep $PRIVILEGED_HELPER_LABEL)
9 |
10 |
11 | if [ -z "$LAUNCHD_OUTPUT" ]
12 | then
13 | echo "Finished successfully."
14 | else
15 | echo "WARNING: $PRIVILEGED_HELPER_LABEL is not removed"
16 | fi
17 |
--------------------------------------------------------------------------------