Files
Leeksov 4647310322 GLEGram 12.5 — Initial public release
Based on Swiftgram 12.5 (Telegram iOS 12.5).
All GLEGram features ported and organized in GLEGram/ folder.

Features: Ghost Mode, Saved Deleted Messages, Content Protection Bypass,
Font Replacement, Fake Profile, Chat Export, Plugin System, and more.

See CHANGELOG_12.5.md for full details.
2026-04-06 09:48:12 +03:00

322 lines
14 KiB
Swift
Executable File

import Foundation
import UIKit
import CoreLocation
#if canImport(SGSimpleSettings)
import SGSimpleSettings
#endif
public final class FakeLocationManager: NSObject {
public static let shared = FakeLocationManager()
private var locationManagers: NSHashTable<CLLocationManager> = NSHashTable.weakObjects()
private var periodicUpdateTimer: Foundation.Timer?
private let timerInterval: TimeInterval = 20.0
private override init() {
super.init()
setupAppLifecycleObservers()
}
private func setupAppLifecycleObservers() {
NotificationCenter.default.addObserver(
self,
selector: #selector(appDidBecomeActive),
name: UIApplication.didBecomeActiveNotification,
object: nil
)
NotificationCenter.default.addObserver(
self,
selector: #selector(appDidEnterBackground),
name: UIApplication.didEnterBackgroundNotification,
object: nil
)
}
@objc private func appDidBecomeActive() {
startPeriodicUpdates()
}
@objc private func appDidEnterBackground() {
stopPeriodicUpdates()
}
private func startPeriodicUpdates() {
if periodicUpdateTimer != nil {
return
}
#if canImport(SGSimpleSettings)
guard SGSimpleSettings.shared.fakeLocationEnabled else {
return
}
sendFakeLocationToAllManagers()
periodicUpdateTimer = Foundation.Timer.scheduledTimer(
withTimeInterval: timerInterval,
repeats: true
) { [weak self] _ in
self?.sendFakeLocationToAllManagers()
}
if let timer = periodicUpdateTimer {
RunLoop.current.add(timer, forMode: .common)
}
#endif
}
private func stopPeriodicUpdates() {
periodicUpdateTimer?.invalidate()
periodicUpdateTimer = nil
}
private func sendFakeLocationToAllManagers() {
#if canImport(SGSimpleSettings)
guard SGSimpleSettings.shared.fakeLocationEnabled else {
stopPeriodicUpdates()
return
}
let latitude = SGSimpleSettings.shared.fakeLatitude
let longitude = SGSimpleSettings.shared.fakeLongitude
guard latitude != 0.0 && longitude != 0.0 else {
return
}
for manager in locationManagers.allObjects {
sendFakeLocationToManager(manager)
}
#endif
}
func addLocationManager(_ manager: CLLocationManager) {
locationManagers.add(manager)
}
func sendFakeLocationToManager(_ manager: CLLocationManager) {
#if canImport(SGSimpleSettings)
guard SGSimpleSettings.shared.fakeLocationEnabled else { return }
let latitude = SGSimpleSettings.shared.fakeLatitude
let longitude = SGSimpleSettings.shared.fakeLongitude
guard latitude != 0.0 && longitude != 0.0 else { return }
let fakeLocation = CLLocation(
coordinate: CLLocationCoordinate2D(latitude: latitude, longitude: longitude),
altitude: 0,
horizontalAccuracy: 10,
verticalAccuracy: 10,
timestamp: Date()
)
let fakeLocations = [fakeLocation]
if let delegate = manager.delegate {
delegate.locationManager?(manager, didUpdateLocations: fakeLocations)
}
#endif
}
}
extension CLLocationManager {
private static var swizzled = false
private static var originalStartUpdatingLocationIMP: IMP?
private static var originalRequestLocationIMP: IMP?
private static var originalLocationGetterIMP: IMP?
private static var originalSetDelegateIMP: IMP?
private static var originalRequestAlwaysAuthorizationIMP: IMP?
private static var originalRequestWhenInUseAuthorizationIMP: IMP?
private static var originalAuthorizationStatusGetterIMP: IMP?
private static var originalStaticAuthorizationStatusIMP: IMP?
public static func swizzleLocationMethods() {
guard !swizzled else { return }
swizzled = true
let startUpdatingLocationSelector = #selector(CLLocationManager.startUpdatingLocation)
let requestLocationSelector = #selector(CLLocationManager.requestLocation)
let locationGetterSelector = #selector(getter: CLLocationManager.location)
let setDelegateSelector = #selector(setter: CLLocationManager.delegate)
let requestAlwaysAuthorizationSelector = #selector(CLLocationManager.requestAlwaysAuthorization)
let requestWhenInUseAuthorizationSelector = #selector(CLLocationManager.requestWhenInUseAuthorization)
let authorizationStatusSelector = NSSelectorFromString("authorizationStatus")
let staticAuthorizationStatusSelector = #selector(CLLocationManager.authorizationStatus)
if let method = class_getInstanceMethod(CLLocationManager.self, startUpdatingLocationSelector),
let swizzledMethod = class_getInstanceMethod(CLLocationManager.self, #selector(CLLocationManager.swizzled_startUpdatingLocation)) {
originalStartUpdatingLocationIMP = method_getImplementation(method)
method_exchangeImplementations(method, swizzledMethod)
}
if #available(iOS 9.0, *) {
if let method = class_getInstanceMethod(CLLocationManager.self, requestLocationSelector),
let swizzledMethod = class_getInstanceMethod(CLLocationManager.self, #selector(CLLocationManager.swizzled_requestLocation)) {
originalRequestLocationIMP = method_getImplementation(method)
method_exchangeImplementations(method, swizzledMethod)
}
}
if let method = class_getInstanceMethod(CLLocationManager.self, locationGetterSelector),
let swizzledMethod = class_getInstanceMethod(CLLocationManager.self, #selector(CLLocationManager.swizzled_location)) {
originalLocationGetterIMP = method_getImplementation(method)
method_exchangeImplementations(method, swizzledMethod)
}
if let method = class_getInstanceMethod(CLLocationManager.self, setDelegateSelector),
let swizzledMethod = class_getInstanceMethod(CLLocationManager.self, #selector(CLLocationManager.swizzled_setDelegate(_:))) {
originalSetDelegateIMP = method_getImplementation(method)
method_exchangeImplementations(method, swizzledMethod)
}
if let method = class_getInstanceMethod(CLLocationManager.self, requestAlwaysAuthorizationSelector),
let swizzledMethod = class_getInstanceMethod(CLLocationManager.self, #selector(CLLocationManager.swizzled_requestAlwaysAuthorization)) {
originalRequestAlwaysAuthorizationIMP = method_getImplementation(method)
method_exchangeImplementations(method, swizzledMethod)
}
if let method = class_getInstanceMethod(CLLocationManager.self, requestWhenInUseAuthorizationSelector),
let swizzledMethod = class_getInstanceMethod(CLLocationManager.self, #selector(CLLocationManager.swizzled_requestWhenInUseAuthorization)) {
originalRequestWhenInUseAuthorizationIMP = method_getImplementation(method)
method_exchangeImplementations(method, swizzledMethod)
}
if #available(iOS 14.0, *) {
if let method = class_getInstanceMethod(CLLocationManager.self, authorizationStatusSelector),
let swizzledMethod = class_getInstanceMethod(CLLocationManager.self, #selector(CLLocationManager.swizzled_authorizationStatus)) {
originalAuthorizationStatusGetterIMP = method_getImplementation(method)
method_exchangeImplementations(method, swizzledMethod)
}
}
if let method = class_getClassMethod(CLLocationManager.self, staticAuthorizationStatusSelector),
let swizzledMethod = class_getClassMethod(CLLocationManager.self, #selector(CLLocationManager.swizzled_staticAuthorizationStatus)) {
originalStaticAuthorizationStatusIMP = method_getImplementation(method)
method_exchangeImplementations(method, swizzledMethod)
}
}
@objc private func swizzled_setDelegate(_ delegate: CLLocationManagerDelegate?) {
if let originalIMP = CLLocationManager.originalSetDelegateIMP {
typealias MethodType = @convention(c) (AnyObject, Selector, CLLocationManagerDelegate?) -> Void
let methodFunc = unsafeBitCast(originalIMP, to: MethodType.self)
methodFunc(self, #selector(setter: CLLocationManager.delegate), delegate)
}
FakeLocationManager.shared.addLocationManager(self)
#if canImport(SGSimpleSettings)
if SGSimpleSettings.shared.fakeLocationEnabled {
let latitude = SGSimpleSettings.shared.fakeLatitude
let longitude = SGSimpleSettings.shared.fakeLongitude
if latitude != 0.0 && longitude != 0.0 {
self.stopUpdatingLocation()
FakeLocationManager.shared.sendFakeLocationToManager(self)
}
}
#endif
}
@objc private func swizzled_startUpdatingLocation() {
FakeLocationManager.shared.addLocationManager(self)
#if canImport(SGSimpleSettings)
if SGSimpleSettings.shared.fakeLocationEnabled {
let latitude = SGSimpleSettings.shared.fakeLatitude
let longitude = SGSimpleSettings.shared.fakeLongitude
if latitude != 0.0 && longitude != 0.0 {
FakeLocationManager.shared.sendFakeLocationToManager(self)
return
}
}
#endif
if let originalIMP = CLLocationManager.originalStartUpdatingLocationIMP {
typealias MethodType = @convention(c) (AnyObject, Selector) -> Void
let methodFunc = unsafeBitCast(originalIMP, to: MethodType.self)
methodFunc(self, #selector(startUpdatingLocation))
}
}
@available(iOS 9.0, *)
@objc private func swizzled_requestLocation() {
#if canImport(SGSimpleSettings)
if SGSimpleSettings.shared.fakeLocationEnabled {
let latitude = SGSimpleSettings.shared.fakeLatitude
let longitude = SGSimpleSettings.shared.fakeLongitude
if latitude != 0.0 && longitude != 0.0 {
FakeLocationManager.shared.sendFakeLocationToManager(self)
return
}
}
#endif
if let originalIMP = CLLocationManager.originalRequestLocationIMP {
typealias MethodType = @convention(c) (AnyObject, Selector) -> Void
let methodFunc = unsafeBitCast(originalIMP, to: MethodType.self)
methodFunc(self, #selector(requestLocation))
}
}
@objc private func swizzled_location() -> CLLocation? {
#if canImport(SGSimpleSettings)
if SGSimpleSettings.shared.fakeLocationEnabled {
let latitude = SGSimpleSettings.shared.fakeLatitude
let longitude = SGSimpleSettings.shared.fakeLongitude
if latitude != 0.0 && longitude != 0.0 {
return CLLocation(
coordinate: CLLocationCoordinate2D(latitude: latitude, longitude: longitude),
altitude: 0,
horizontalAccuracy: 10,
verticalAccuracy: 10,
timestamp: Date()
)
}
}
#endif
if let originalIMP = CLLocationManager.originalLocationGetterIMP {
typealias MethodType = @convention(c) (AnyObject, Selector) -> CLLocation?
let methodFunc = unsafeBitCast(originalIMP, to: MethodType.self)
return methodFunc(self, #selector(getter: CLLocationManager.location))
}
return nil
}
@objc private func swizzled_requestAlwaysAuthorization() {
if let originalIMP = CLLocationManager.originalRequestAlwaysAuthorizationIMP {
typealias MethodType = @convention(c) (AnyObject, Selector) -> Void
let methodFunc = unsafeBitCast(originalIMP, to: MethodType.self)
methodFunc(self, #selector(requestAlwaysAuthorization))
}
}
@objc private func swizzled_requestWhenInUseAuthorization() {
if let originalIMP = CLLocationManager.originalRequestWhenInUseAuthorizationIMP {
typealias MethodType = @convention(c) (AnyObject, Selector) -> Void
let methodFunc = unsafeBitCast(originalIMP, to: MethodType.self)
methodFunc(self, #selector(requestWhenInUseAuthorization))
}
}
@available(iOS 14.0, *)
@objc private func swizzled_authorizationStatus() -> CLAuthorizationStatus {
if let originalIMP = CLLocationManager.originalAuthorizationStatusGetterIMP {
typealias MethodType = @convention(c) (AnyObject, Selector) -> CLAuthorizationStatus
let methodFunc = unsafeBitCast(originalIMP, to: MethodType.self)
return methodFunc(self, NSSelectorFromString("authorizationStatus"))
}
return .notDetermined
}
@objc private static func swizzled_staticAuthorizationStatus() -> CLAuthorizationStatus {
if let originalIMP = CLLocationManager.originalStaticAuthorizationStatusIMP {
typealias MethodType = @convention(c) (AnyClass, Selector) -> CLAuthorizationStatus
let methodFunc = unsafeBitCast(originalIMP, to: MethodType.self)
return methodFunc(CLLocationManager.self, #selector(CLLocationManager.authorizationStatus))
}
return .notDetermined
}
}