initial commit

This commit is contained in:
Sam
2023-03-26 17:31:42 -04:00
commit e3b5b090fb
51 changed files with 4222 additions and 0 deletions

10
CheetahIPC/CheetahIPC.h Normal file
View File

@ -0,0 +1,10 @@
#import <Foundation/Foundation.h>
//! Project version number for CheetahIPC.
FOUNDATION_EXPORT double CheetahIPCVersionNumber;
//! Project version string for CheetahIPC.
FOUNDATION_EXPORT const unsigned char CheetahIPCVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <CheetahIPC/PublicHeader.h>

67
CheetahIPC/Client.swift Normal file
View File

@ -0,0 +1,67 @@
import CoreFoundation
import UserNotifications
public enum IPCClientError: Error {
case createRemoteFailure
case sendRequestFailure(Int32)
}
public class IPCClient {
let remote: CFMessagePort
public init(messagePortName: String) throws {
if let remote = CFMessagePortCreateRemote(nil, messagePortName as CFString) {
self.remote = remote
} else {
throw IPCClientError.createRemoteFailure
}
}
public func sendRequest(msgid: Int32, data: Data) throws -> Data? {
var responseData: Unmanaged<CFData>? = nil
let result = CFMessagePortSendRequest(
remote,
msgid,
data as CFData,
1.0, // sendTimeout
1.0, // rcvTimeout
CFRunLoopMode.defaultMode.rawValue,
&responseData)
if result == kCFMessagePortSuccess {
return responseData?.takeRetainedValue() as Data?
} else {
throw IPCClientError.sendRequestFailure(result)
}
}
}
public extension IPCClient {
func encode(_ object: Encodable) throws -> Data {
return try PropertyListEncoder().encode(object)
}
func encode(_ object: NSCoding) throws -> Data {
return try NSKeyedArchiver.archivedData(withRootObject: object, requiringSecureCoding: true)
}
func decode<T: Decodable>(_ data: Data) throws -> T {
return try PropertyListDecoder().decode(T.self, from: data)
}
func decode<T>(_ data: Data) throws -> T? where T: NSObject, T: NSCoding {
return try NSKeyedUnarchiver.unarchivedObject(ofClass: T.self, from: data)
}
func sendMessage(id: any RawRepresentable<Int32>, withObject object: NSCoding) throws {
_ = try sendRequest(msgid: id.rawValue, data: encode(object))
}
func sendMessage<T: Decodable>(id: any RawRepresentable<Int32>, withObject object: NSCoding) throws -> T? {
guard let resultData = try sendRequest(msgid: id.rawValue, data: encode(object)) else {
return nil
}
return try decode(resultData)
}
}

17
CheetahIPC/Messages.swift Normal file
View File

@ -0,0 +1,17 @@
import Foundation
import SwiftUI
public enum MessagePortName: String {
case browserExtensionServer = "org.phrack.Cheetah.BrowserExtensionServer"
}
public enum IPCMessage: Int32 {
case browserExtensionMessage = 1
}
public struct BrowserExtensionMessage: Codable {
public var mode: String
public var files = [String: String]()
public var logs = [String: String]()
public var navigationStart: Int
}

95
CheetahIPC/Server.swift Normal file
View File

@ -0,0 +1,95 @@
import CoreFoundation
func serverCallback(local: CFMessagePort?, msgid: Int32, data: CFData?, info: UnsafeMutableRawPointer?) -> Unmanaged<CFData>? {
let server = Unmanaged<IPCServer>.fromOpaque(info!).takeUnretainedValue()
let responseData = server.delegate?.handleMessageWithID(msgid, data: data! as Data)
if let responseData = responseData as? NSData,
let cfdata = CFDataCreate(nil, responseData.bytes, responseData.length) {
return Unmanaged.passRetained(cfdata)
} else {
return nil
}
}
public protocol IPCServerDelegate: AnyObject {
func handleMessageWithID(_ msgid: Int32, data: Data) -> Data?
}
open class NSCodingHandler<RequestObject>: NSObject, IPCServerDelegate {
public typealias Handler = (RequestObject?) -> Encodable?
public let messageID: Int32
public var handler: Handler?
public init(respondsTo id: any RawRepresentable<Int32>, _ handler: Handler? = nil) {
self.messageID = id.rawValue
self.handler = handler
}
public func handleMessageWithID(_ msgid: Int32, data: Data) -> Data? {
let object = NSKeyedUnarchiver.unarchiveObject(with: data) as? RequestObject
if let handler = handler, let result = handler(object) {
return try? NSKeyedArchiver.archivedData(withRootObject: result, requiringSecureCoding: false)
} else {
return nil
}
}
}
open class JSONHandler<RequestObject: Decodable>: IPCServerDelegate {
public typealias Handler = (RequestObject?) -> Encodable?
public let messageID: Int32
public var handler: Handler?
public init(respondsTo id: any RawRepresentable<Int32>, _ handler: Handler? = nil) {
self.messageID = id.rawValue
self.handler = handler
}
public func handleMessageWithID(_ msgid: Int32, data: Data) -> Data? {
let object = try? JSONDecoder().decode(RequestObject.self, from: data)
if let object = object, let handler = handler, let result = handler(object) {
return try? NSKeyedArchiver.archivedData(withRootObject: result, requiringSecureCoding: false)
} else {
return nil
}
}
}
public class IPCServer: NSObject {
public weak var delegate: IPCServerDelegate?
/// Create the local message port then register an input source for it
public func addSourceForNewLocalMessagePort(name: String, toRunLoop runLoop: CFRunLoop!) {
if let messagePort = createMessagePort(name: name) {
addSource(messagePort: messagePort, toRunLoop: runLoop)
}
}
/// Create a local message port with the specified name
///
/// Incoming messages will be routed to this object's handleMessageWithID(,data:) method.
func createMessagePort(name: String) -> CFMessagePort? {
var context = CFMessagePortContext(
version: 0,
info: Unmanaged.passUnretained(self).toOpaque(),
retain: nil,
release: nil,
copyDescription: nil)
var shouldFreeInfo: DarwinBoolean = false
return CFMessagePortCreateLocal(
nil,
name as CFString,
serverCallback,
&context,
&shouldFreeInfo)
}
/// Create an input source for the specified message port and add it to the specified run loop
func addSource(messagePort: CFMessagePort, toRunLoop runLoop: CFRunLoop) {
let source = CFMessagePortCreateRunLoopSource(nil, messagePort, 0)
CFRunLoopAddSource(runLoop, source, CFRunLoopMode.commonModes)
}
}