Files
ichmagmaus111andClaude Opus 5.5 0622057a4f Ghostgram: open-source release
Ghostgram for iOS, rebuilt from scratch on Telegram iOS 13.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 17:57:09 +01:00

102 lines
3.5 KiB
Swift

import CoreFoundation
import Foundation
enum WebProxyPageStatus: String, CaseIterable, Equatable {
case connecting
case reconnecting
case connected
case failed
}
enum WebProxyControlMessage: Equatable {
case initialize(nonce: String)
case status(WebProxyPageStatus)
case traffic(up: UInt64, down: UInt64)
case close
static func decode(_ value: String) throws -> WebProxyControlMessage {
guard value.utf8.count <= 4096,
let data = value.data(using: .utf8),
let object = try? JSONSerialization.jsonObject(with: data),
let dictionary = object as? [String: Any],
let type = dictionary["t"] as? String else {
throw WebProxyControlMessageError.invalidMessage
}
switch type {
case "tproxy-android-init":
guard Self.hasExactKeys(dictionary, ["nonce", "t", "v"]),
Self.integer(dictionary["v"]) == 1,
let nonce = dictionary["nonce"] as? String,
Self.isCanonicalNonce(nonce) else {
throw WebProxyControlMessageError.invalidInitialization
}
return .initialize(nonce: nonce)
case "status":
guard Self.hasExactKeys(dictionary, ["state", "t"]),
let rawStatus = dictionary["state"] as? String,
let status = WebProxyPageStatus(rawValue: rawStatus) else {
throw WebProxyControlMessageError.invalidMessage
}
return .status(status)
case "traffic":
guard Self.hasExactKeys(dictionary, ["down", "t", "up"]),
let up = Self.trafficCount(dictionary["up"]),
let down = Self.trafficCount(dictionary["down"]) else {
throw WebProxyControlMessageError.invalidMessage
}
return .traffic(up: up, down: down)
case "close":
guard Self.hasExactKeys(dictionary, ["t"]) else {
throw WebProxyControlMessageError.invalidMessage
}
return .close
default:
throw WebProxyControlMessageError.invalidMessage
}
}
private static func hasExactKeys(_ dictionary: [String: Any], _ keys: Set<String>) -> Bool {
return Set(dictionary.keys) == keys
}
private static func integer(_ value: Any?) -> UInt64? {
guard let number = value as? NSNumber,
CFGetTypeID(number) != CFBooleanGetTypeID() else {
return nil
}
let doubleValue = number.doubleValue
guard doubleValue.isFinite,
doubleValue >= 0.0,
doubleValue.rounded(.towardZero) == doubleValue,
doubleValue <= Double(UInt64.max) else {
return nil
}
return number.uint64Value
}
private static func trafficCount(_ value: Any?) -> UInt64? {
guard let value = Self.integer(value),
value <= UInt64(WebProxyProtocol.maximumQueuedBytes) else {
return nil
}
return value
}
private static func isCanonicalNonce(_ value: String) -> Bool {
guard value.utf8.count == 43 else { return false }
return value.utf8.allSatisfy { byte in
return (byte >= 48 && byte <= 57)
|| (byte >= 65 && byte <= 90)
|| (byte >= 97 && byte <= 122)
|| byte == 45
|| byte == 95
}
}
}
enum WebProxyControlMessageError: Error, Equatable {
case invalidMessage
case invalidInitialization
}