Jelajahi Sumber

update connect with getipdomain, webview with cookie and useragent, get Image with cookie and useragent

alqindiirsyam 1 tahun lalu
induk
melakukan
bf16bcbe24
25 mengubah file dengan 583 tambahan dan 76 penghapusan
  1. 3 3
      appbuilder-ios/AppBuilder/AppBuilder/AppDelegate.swift
  2. 1 1
      appbuilder-ios/AppBuilder/AppBuilder/FirstTabViewController.swift
  3. 1 1
      appbuilder-ios/AppBuilder/AppBuilder/FourthTabViewController.swift
  4. 2 2
      appbuilder-ios/AppBuilder/AppBuilder/PrefsUtil.swift
  5. 1 1
      appbuilder-ios/AppBuilder/AppBuilder/SecondTabViewController.swift
  6. 1 1
      appbuilder-ios/AppBuilder/AppBuilder/ThirdTabViewController.swift
  7. 5 5
      appbuilder-ios/AppBuilder/AppBuilder/ViewController.swift
  8. TEMPAT SAMPAH
      appbuilder-ios/DigiXLite/DigiXLite.xcworkspace/xcuserdata/akhmadalqindiirsyam.xcuserdatad/UserInterfaceState.xcuserstate
  9. 116 21
      appbuilder-ios/DigiXLite/DigiXLite/Source/DigiX.swift
  10. 1 1
      appbuilder-ios/DigiXLite/DigiXLite/Source/Download.swift
  11. 1 1
      appbuilder-ios/DigiXLite/DigiXLite/Source/Extension.swift
  12. 1 1
      appbuilder-ios/DigiXLite/DigiXLite/Source/FloatingButton/FloatingButton.swift
  13. 4 0
      appbuilder-ios/DigiXLite/DigiXLite/Source/IncomingThread.swift
  14. 1 1
      appbuilder-ios/DigiXLite/DigiXLite/Source/Network.swift
  15. 159 4
      appbuilder-ios/DigiXLite/DigiXLite/Source/Utils.swift
  16. 1 1
      appbuilder-ios/DigiXLite/DigiXLite/Source/View/BNIView/BNIBookingWebView.swift
  17. 1 1
      appbuilder-ios/DigiXLite/DigiXLite/Source/View/Chat/ChatGPTBotView.swift
  18. 1 1
      appbuilder-ios/NexilisLite/NexilisLite/Source/Download.swift
  19. 1 1
      appbuilder-ios/NexilisLite/NexilisLite/Source/Extension.swift
  20. 1 1
      appbuilder-ios/NexilisLite/NexilisLite/Source/FloatingButton/FloatingButton.swift
  21. 4 0
      appbuilder-ios/NexilisLite/NexilisLite/Source/IncomingThread.swift
  22. 1 1
      appbuilder-ios/NexilisLite/NexilisLite/Source/Network.swift
  23. 116 22
      appbuilder-ios/NexilisLite/NexilisLite/Source/Nexilis.swift
  24. 159 4
      appbuilder-ios/NexilisLite/NexilisLite/Source/Utils.swift
  25. 1 1
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/BNIView/BNIBookingWebView.swift

+ 3 - 3
appbuilder-ios/AppBuilder/AppBuilder/AppDelegate.swift

@@ -76,11 +76,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
 extension AppDelegate: ConnectDelegate, UNUserNotificationCenterDelegate {
     
     func onSuccess(userId: String) {
-        print(#function, "userId: \(userId)")
+        //print(#function, "userId: \(userId)")
     }
     
     func onFailed(error: String) {
-        print(#function, "error: \(error)")
+        //print(#function, "error: \(error)")
     }
     
     func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
@@ -89,7 +89,7 @@ extension AppDelegate: ConnectDelegate, UNUserNotificationCenterDelegate {
     }
     
     func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
-        print(error)
+        //print(error)
     }
     
     func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

+ 1 - 1
appbuilder-ios/AppBuilder/AppBuilder/FirstTabViewController.swift

@@ -37,7 +37,7 @@ class FirstTabViewController: UIViewController, UIScrollViewDelegate, UIGestureR
         tapGesture.delegate = self
         let configuration = WKWebViewConfiguration()
         configuration.allowsInlineMediaPlayback = true
-        let customUserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 Safari/604.1 easySoftIndonesia"
+        let customUserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 Safari/604.1 \(Utils.getUserAgent())"
         let finalUserAgent = "\(customUserAgent)"
         configuration.applicationNameForUserAgent = finalUserAgent
         webView = WKWebView(frame: .zero, configuration: configuration)

+ 1 - 1
appbuilder-ios/AppBuilder/AppBuilder/FourthTabViewController.swift

@@ -303,7 +303,7 @@ public class FourthTabViewController: UIViewController, UITableViewDelegate, UIT
                 var bgChoosen = ""
                 let arrayBg = listBg.split(separator: ",")
                 bgChoosen = String(arrayBg[Int.random(in: 0..<arrayBg.count)])
-                ViewController.getDataImageFromUrl(from: URL(string: PrefsUtil.getURLBase() + "/dashboardv2/uploads/background/" + bgChoosen)!) { data, response, error in
+                Utils.fetchDataWithCookiesAndUserAgent(from: URL(string: PrefsUtil.getURLBase() + "get_file_from_path?img=" + bgChoosen)!) { data, response, error in
                     guard let data = data, error == nil else { return }
                     // always update the UI from the main thread
                     DispatchQueue.main.async() { [self] in

+ 2 - 2
appbuilder-ios/AppBuilder/AppBuilder/PrefsUtil.swift

@@ -61,10 +61,10 @@ class PrefsUtil {
         return UserDefaults.standard.string(forKey: "app_builder_background")
     }
     static func getUrlSS() -> String? {
-        return PrefsUtil.getURLBase() + "dashboardv2/uploads/splashscreen/" + PrefsUtil.getIconSS()!
+        return PrefsUtil.getURLBase() + "get_file_from_path?img=" + PrefsUtil.getIconSS()!
     }
     static func getUrlDock() -> String? {
-        return PrefsUtil.getURLBase() + "dashboardv2/uploads/fb_icon/" + PrefsUtil.getIconDock()
+        return PrefsUtil.getURLBase() + "get_file_from_path?img=" + PrefsUtil.getIconDock()
     }
     
     static func getURLPrivacyPolicy() -> String {

+ 1 - 1
appbuilder-ios/AppBuilder/AppBuilder/SecondTabViewController.swift

@@ -382,7 +382,7 @@ class SecondTabViewController: UIViewController, UIScrollViewDelegate, UIGesture
                 var bgChoosen = ""
                 let arrayBg = listBg.split(separator: ",")
                 bgChoosen = String(arrayBg[Int.random(in: 0..<arrayBg.count)])
-                ViewController.getDataImageFromUrl(from: URL(string: PrefsUtil.getURLBase() + "/dashboardv2/uploads/background/" + bgChoosen)!) { data, response, error in
+                Utils.fetchDataWithCookiesAndUserAgent(from: URL(string: PrefsUtil.getURLBase() + "get_file_from_path?img=" + bgChoosen)!) { data, response, error in
                     guard let data = data, error == nil else { return }
                     // always update the UI from the main thread
                     DispatchQueue.main.async() { [self] in

+ 1 - 1
appbuilder-ios/AppBuilder/AppBuilder/ThirdTabViewController.swift

@@ -38,7 +38,7 @@ class ThirdTabViewController: UIViewController, UIScrollViewDelegate, UIGestureR
         tapGesture.delegate = self
         let configuration = WKWebViewConfiguration()
         configuration.allowsInlineMediaPlayback = true
-        let customUserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 Safari/604.1 easySoftIndonesia"
+        let customUserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 Safari/604.1 \(Utils.getUserAgent())"
         let finalUserAgent = "\(customUserAgent)"
         configuration.applicationNameForUserAgent = finalUserAgent
         webView = WKWebView(frame: .zero, configuration: configuration)

+ 5 - 5
appbuilder-ios/AppBuilder/AppBuilder/ViewController.swift

@@ -60,7 +60,7 @@ class ViewController: UITabBarController, UITabBarControllerDelegate, SettingMAB
         super.viewDidLoad()
         DispatchQueue.main.async { [self] in
             while !Utils.getFinishInitPrefsr() {
-                print("WAITING PREFS DONE")
+                //print("WAITING PREFS DONE")
             }
             startView()
         }
@@ -453,7 +453,7 @@ class ViewController: UITabBarController, UITabBarControllerDelegate, SettingMAB
                 })
             } else {
                 DispatchQueue.global().async {
-                    ViewController.getDataImageFromUrl(from: URL(string: PrefsUtil.getUrlDock()!)!) { data, response, error in
+                    Utils.fetchDataWithCookiesAndUserAgent(from: URL(string: PrefsUtil.getUrlDock()!)!) { data, response, error in
                         guard let data = data, error == nil else { return }
                         // always update the UI from the main thread
                         DispatchQueue.main.async() {
@@ -614,7 +614,7 @@ class ViewController: UITabBarController, UITabBarControllerDelegate, SettingMAB
                     var bgChoosen = ""
                     let arrayBg = listBg.split(separator: ",")
                     bgChoosen = String(arrayBg[Int.random(in: 0..<arrayBg.count)])
-                    ViewController.getDataImageFromUrl(from: URL(string: PrefsUtil.getURLBase() + "/dashboardv2/uploads/background/" + bgChoosen)!) { data, response, error in
+                    Utils.fetchDataWithCookiesAndUserAgent(from: URL(string: PrefsUtil.getURLBase() + "get_file_from_path?img=" + bgChoosen)!) { data, response, error in
                         guard let data = data, error == nil else { return }
                         // always update the UI from the main thread
                         DispatchQueue.main.async() {
@@ -686,7 +686,7 @@ class ViewController: UITabBarController, UITabBarControllerDelegate, SettingMAB
                     var bgChoosen = ""
                     let arrayBg = listBg.split(separator: ",")
                     bgChoosen = String(arrayBg[Int.random(in: 0..<arrayBg.count)])
-                    ViewController.getDataImageFromUrl(from: URL(string: PrefsUtil.getURLBase() + "/dashboardv2/uploads/background/" + bgChoosen)!) { data, response, error in
+                    Utils.fetchDataWithCookiesAndUserAgent(from: URL(string: PrefsUtil.getURLBase() + "get_file_from_path?img=" + bgChoosen)!) { data, response, error in
                         guard let data = data, error == nil else { return }
                         // always update the UI from the main thread
                         DispatchQueue.main.async() {
@@ -1048,7 +1048,7 @@ class ViewController: UITabBarController, UITabBarControllerDelegate, SettingMAB
                             let icon = customIcons[i]
                             listPullFB.append("\(package_id)|\(app_id)")
                             DispatchQueue.global().async {
-                                ViewController.getDataImageFromUrl(from: URL(string: "https://nexilis.io/dashboardv2/uploads/fb_icon/\(icon)")!) { data, response, error in
+                                ViewController.getDataImageFromUrl(from: URL(string: PrefsUtil.getURLBase() + "get_file_from_path?img=\(icon)")!) { data, response, error in
                                     guard let data = data, error == nil else { return }
                                     // always update the UI from the main thread
                                     DispatchQueue.main.async() {

TEMPAT SAMPAH
appbuilder-ios/DigiXLite/DigiXLite.xcworkspace/xcuserdata/akhmadalqindiirsyam.xcuserdatad/UserInterfaceState.xcuserstate


+ 116 - 21
appbuilder-ios/DigiXLite/DigiXLite/Source/DigiX.swift

@@ -139,31 +139,33 @@ public class DigiX: NSObject {
             imageCache.countLimit = 100
             imageCache.totalCostLimit = 1024 * 1024 * 200
             
-            let address = DigiX.getAddress(apiKey:apiKey)
-            if address.count == 0 {
+            let address = DigiX.getAddressNew(apiKey:apiKey)
+//            print("ADDRESS \(address)")
+            if address.isEmpty {
                 return
             }
-            UserDefaults.standard.set(address, forKey: "address")
-            UserDefaults.standard.set(address[0], forKey: "server")
-            
+//            UserDefaults.standard.set(address, forKey: "address")
+//            UserDefaults.standard.set(address[0], forKey: "server")
+//
             DigiX.dispatch = DispatchGroup()
             DigiX.dispatch?.enter()
-            var server = UserDefaults.standard.string(forKey: "server")
-            if let s = server, let a = UserDefaults.standard.stringArray(forKey: "address"), s != a[0] {
-                server = a[0]
-                UserDefaults.standard.set(server, forKey: "server")
-            }
-            var ip = ""
-            var port = 0
-            if let s = server {
-                let data = s.split(separator: ":")
-                ip = String(data[0])
-                if let p = Int(data[1]) {
-                    port = p
-                }
-            }
-            DigiX.ADDRESS = ip
-            DigiX.PORT = port
+//            var server = UserDefaults.standard.string(forKey: "server")
+//            if let s = server, let a = UserDefaults.standard.stringArray(forKey: "address"), s != a[0] {
+//                server = a[0]
+//                UserDefaults.standard.set(server, forKey: "server")
+//            }
+//            var ip = ""
+//            var port = 0
+//            if let s = server {
+//                let data = s.split(separator: ":")
+//                ip = String(data[0])
+//                if let p = Int(data[1]) {
+//                    port = p
+//                }
+//            }
+            DigiX.ADDRESS = address.components(separatedBy: ":")[0]
+            DigiX.PORT = Int(address.components(separatedBy: ":")[1]) ?? 0
+//            print("IP PORT \(DigiX.ADDRESS) <> \(DigiX.PORT)")
             //print(API.sGetVersion())
             var id = ""
             if let device_id = UserDefaults.standard.string(forKey: "device_id") {
@@ -572,6 +574,99 @@ public class DigiX: NSObject {
         return result
     }
     
+    static func getAddressNew(apiKey: String) -> String {
+        var result = ""
+        
+        if !Utils.getHarcodedIp().isEmpty {
+            result = Utils.getHarcodedIp()
+            return result
+        }
+        
+        let url = URL(string: "\(Utils.getDomainOpr())dipp/NuN1v3rs3/Qm3r4i0/get_ip_domain?account=\(apiKey)")!
+        let urlConfig = URLSessionConfiguration.default
+        urlConfig.requestCachePolicy = .returnCacheDataElseLoad
+        urlConfig.timeoutIntervalForRequest = 10.0
+        urlConfig.timeoutIntervalForResource = 10.0
+        let semaphore = DispatchSemaphore(value: 0)
+        let task = URLSession(configuration: urlConfig).dataTask(with: url) {(data, response, error) in
+            guard let data = data,
+                let url = response?.url,
+                let httpResponse = response as? HTTPURLResponse,
+                let fields = httpResponse.allHeaderFields as? [String: String] else {
+                semaphore.signal()
+                return
+            }
+            
+            let cookies = HTTPCookie.cookies(withResponseHeaderFields: fields, for: url)
+            HTTPCookieStorage.shared.setCookies(cookies, for: url, mainDocumentURL: nil)
+
+            let dataEncode = String(data: data, encoding: .utf8)!
+//            print("dataEncode \(dataEncode.trimmingCharacters(in: .whitespacesAndNewlines))")
+//            print("decrypt \(Utils.decrypt(str: "4=sm<wmpm1ir==>wtxxl"))")
+            if !dataEncode.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
+                let dataDecodeBase64 = String(data: Data(base64Encoded: dataEncode)!, encoding: .utf8)!
+                let dataRealDecode = Utils.decrypt(str: dataDecodeBase64)
+//                print("dataRealDecode \(dataRealDecode)")
+                do {
+                    if let jsonData = dataRealDecode.data(using: .utf8), let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
+                        var newDomain = jsonObject["domain"] as! String
+                        let jsonAddress = jsonObject["address"] as! [[String: Any]]
+                        let newIp = jsonAddress[0]["ip"] as! String
+                        let newPort = jsonAddress[0]["portI"] as! String
+                        if newDomain.substring(from: newDomain.count-1, to: nil) != "/" {
+                            newDomain += "/"
+                        }
+                        if (newIp+":"+newPort) != Utils.getIpOpr() || newDomain != Utils.getDomainOpr() {
+                            //check new domain
+                            if checkNewDomain(newDomain) {
+                                Utils.setDomainOpr(value: newDomain)
+                                Utils.setIpPortOpr(value: (newIp+":"+newPort))
+                            }
+                        }
+                    }
+                } catch {
+                    
+                }
+            }
+            semaphore.signal()
+        }
+        task.resume()
+        _ = semaphore.wait(timeout: .distantFuture)
+        result = Utils.getIpOpr()
+        //print("[App] getAddress:", result)
+        return result
+    }
+    
+    private static func checkNewDomain(_ newDomain: String) -> Bool {
+        var result = false
+        let url = URL(string: "\(newDomain)dipp/NuN1v3rs3/Qm3r4i0/get_ip_domain?account=\(DigiX.sAPIKey)")!
+        let urlConfig = URLSessionConfiguration.default
+        urlConfig.requestCachePolicy = .returnCacheDataElseLoad
+        urlConfig.timeoutIntervalForRequest = 10.0
+        urlConfig.timeoutIntervalForResource = 10.0
+        let semaphore = DispatchSemaphore(value: 0)
+        let task = URLSession(configuration: urlConfig).dataTask(with: url) {(data, response, error) in
+            if let httpResponse = response as? HTTPURLResponse {
+                if httpResponse.statusCode == 200 {
+                    guard let url = response?.url,
+                        let fields = httpResponse.allHeaderFields as? [String: String] else {
+                        semaphore.signal()
+                        return
+                    }
+                    
+                    let cookies = HTTPCookie.cookies(withResponseHeaderFields: fields, for: url)
+                    HTTPCookieStorage.shared.setCookies(cookies, for: url, mainDocumentURL: nil)
+                    
+                    result = true
+                }
+            }
+            semaphore.signal()
+        }
+        task.resume()
+        _ = semaphore.wait(timeout: .distantFuture)
+        return result
+    }
+    
     static func getCLMUserId() -> String {
         guard let me = UserDefaults.standard.string(forKey: "me") else {
             return ""

+ 1 - 1
appbuilder-ios/DigiXLite/DigiXLite/Source/Download.swift

@@ -23,7 +23,7 @@ public class Download {
     
     var DOWNLOAD_BUFFER = [Data?]()
     var DOWNLOAD_SESSION = [Session]()
-    var DOWNLOAD_URL = Utils.getURLBase()! + "filepalio/image/"
+    var DOWNLOAD_URL = Utils.getURLBase() + "filepalio/image/"
     
     public func start(forKey: String, delegate: DownloadDelegate){
         self.delegate = delegate

+ 1 - 1
appbuilder-ios/DigiXLite/DigiXLite/Source/Extension.swift

@@ -346,7 +346,7 @@ extension NSObject {
 extension URL {
     
     static func palioImage(named: String) -> URL? {
-        return URL(string: Utils.getURLBase()! + "filepalio/image/\(named)")
+        return URL(string: Utils.getURLBase() + "filepalio/image/\(named)")
     }
     
 }

+ 1 - 1
appbuilder-ios/DigiXLite/DigiXLite/Source/FloatingButton/FloatingButton.swift

@@ -289,7 +289,7 @@ public class FloatingButton: UIView {
                         newButton.heightAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB).isActive = true
                         newButton.translatesAutoresizingMaskIntoConstraints = false
                         DispatchQueue.global().async {
-                            let data = try? Data(contentsOf: URL(string: "https://DigiX.io/dashboardv2/uploads/fb_icon/\(icon)")!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
+                            let data = try? Data(contentsOf: URL(string: Utils.getURLBase() + "get_file_from_path?img=\(icon)")!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
                             DispatchQueue.main.async {
                                 if data != nil {
                                     if let image = UIImage(data: data!) {

+ 4 - 0
appbuilder-ios/DigiXLite/DigiXLite/Source/IncomingThread.swift

@@ -256,6 +256,10 @@ class IncomingThread {
                     if json[CoreMessage_TMessageKey.KEY] as! String == "fb_item_with_bg" {
                         Utils.setFBItemBg(value: json[CoreMessage_TMessageKey.VALUE] as! String)
                     }
+                    if json[CoreMessage_TMessageKey.KEY] as! String == "user_agent" {
+                        Utils.setUserAgent(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    }
+                    //print("PrefsInit : \(json)")
                 }
                 Utils.setFinishInitPrefs(value: true)
             } else {

+ 1 - 1
appbuilder-ios/DigiXLite/DigiXLite/Source/Network.swift

@@ -17,7 +17,7 @@ public class Network {
     private var isCancel = false
     private var progress = 0.0
     private var CHUNK_SIZE = 200 * 1024
-    private var UPLOAD_URL = Utils.getURLBase()! + "uploader"
+    private var UPLOAD_URL = Utils.getURLBase() + "uploader"
     
     public init() {}
     

+ 159 - 4
appbuilder-ios/DigiXLite/DigiXLite/Source/Utils.swift

@@ -59,7 +59,7 @@ public final class Utils {
     }
     
     static func getIconCenterAnim2() -> String? {
-        UserDefaults.standard.string(forKey: "pb_fb_icon_center_self_mode2") ?? "https://nexilis.io/dashboardv2/uploads/logofloat/525_411217560576.gif"
+        UserDefaults.standard.string(forKey: "pb_fb_icon_center_self_mode2") ?? Utils.getURLBase() + "get_file_from_path?img=525_411217560576.gif"
     }
     
     static func setIconCenterAnim4(value: String){
@@ -67,7 +67,7 @@ public final class Utils {
     }
     
     static func getIconCenterAnim4() -> String? {
-        UserDefaults.standard.string(forKey: "pb_fb_icon_center_self_mode4") ?? "https://nexilis.io/dashboardv2/uploads/logofloat/semut1.gif"
+        UserDefaults.standard.string(forKey: "pb_fb_icon_center_self_mode4") ?? Utils.getURLBase() + "get_file_from_path?img=semut1.gif"
     }
     
     static func setURLFirstTab(value: String) {
@@ -225,7 +225,7 @@ public final class Utils {
         }
     }
     
-    static func getURLBase() -> String? {
+    static func getURLBase() -> String {
         return UserDefaults.standard.string(forKey: "app_builder_url_base") ?? "https://nexilis.io/"
     }
     
@@ -234,7 +234,7 @@ public final class Utils {
     }
     
     static func getUrlDock() -> String? {
-        return Utils.getURLBase()! + "dashboardv2/uploads/logofloat/" + Utils.getIconDock()
+        return Utils.getURLBase() + "get_file_from_path?img=" + Utils.getIconDock()
     }
     
     static func setDefaultCC(value: String){
@@ -269,7 +269,162 @@ public final class Utils {
         return UserDefaults.standard.string(forKey: "fb_item_with_bg") ?? "1"
     }
     
+    static func setDomainOpr(value: String){
+        UserDefaults.standard.set(value, forKey: "domain_opr")
+    }
+    
+    static func getDomainOpr() -> String {
+        return UserDefaults.standard.string(forKey: "domain_opr") ?? "https://nexilis.io/"
+    }
+    
+    static func setIpPortOpr(value: String){
+        UserDefaults.standard.set(value, forKey: "ip_opr")
+    }
+    
+    static func getIpOpr() -> String {
+        return UserDefaults.standard.string(forKey: "ip_opr") ?? "34.101.172.194:42823"
+    }
+    
+    static func setHarcodedIp(value: String){
+        UserDefaults.standard.set(value, forKey: "harcoded_ip")
+    }
+    
+    static func getHarcodedIp() -> String {
+        return UserDefaults.standard.string(forKey: "harcoded_ip") ?? ""
+    }
+    
+    static func setUserAgent(value: String){
+        UserDefaults.standard.set(value, forKey: "user_agent")
+    }
+    
+    public static func getUserAgent() -> String {
+        return UserDefaults.standard.string(forKey: "user_agent") ?? "easySoftIndonesia"
+    }
+    
+    public static func fetchDataWithCookiesAndUserAgent(from url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> ()) {
+        var request = URLRequest(url: url)
+        request.httpMethod = "GET"
+        request.setValue(Utils.getUserAgent(), forHTTPHeaderField: "User-Agent")
+        let cookies = HTTPCookieStorage.shared.cookies ?? []
+        if let cookieHeader = HTTPCookie.requestHeaderFields(with: cookies)["Cookie"] {
+//            print("listCookiee: \(cookieHeader)")
+            request.setValue(cookieHeader, forHTTPHeaderField: "Cookie")
+        }
+        let task = URLSession.shared.dataTask(with: request, completionHandler: completion)
+        task.resume()
+    }
+    
     public static var inTabChats = false
+    
+    private static let I_BB = 48   // 0
+    private static let I_BBT_1 = 57 // 9
+    private static let I_BAT_1 = 65 // A
+    private static let I_BBT_2 = 90 // Z
+    private static let I_BAT_2 = 97 // a
+    private static let I_BA = 122  // z
+
+    private static let IC_BB = 33   // !
+    private static let IC_BBT_1 = 47 // /
+    private static let IC_BAT_1 = 58 // :
+    private static let IC_BBT_2 = 64 // @
+    private static let IC_BAT_2 = 91 // [
+    private static let IC_BBT_3 = 96 // @
+    private static let IC_BAT_3 = 123 // [
+    private static let IC_BA = 126  // `
+
+    private static var icIGNORE = Set<Int>()
+
+    private static func initIcIgnore() {
+        icIGNORE.insert(10)// \r
+        icIGNORE.insert(13)// \n
+        icIGNORE.insert(32)// <space>
+    }
+    
+    public static func decrypt(str: String) -> String {
+        var arr: [Character]
+        var iRandom = 0
+        var sDecrypt: String
+        iRandom = Int(str.substring(from: 0, to: 0)) ?? 0
+        sDecrypt = getPalindrom(str: str.substring(from: 1, to: nil))
+        arr = Array(sDecrypt)
+        for i in 0..<arr.count {
+            if (isSpecialChar(ch: arr[i])) {
+                arr[i] = getBeforecChar(ch: arr[i], inc: iRandom)
+            } else {
+                arr[i] = getBeforeChar(ch: arr[i], inc: iRandom)
+            }
+        }
+        return String(arr)
+    }
+    
+    private static func isSpecialChar(ch: Character) -> Bool {
+        let ch = Int(ch.asciiValue ?? 0)
+        return (ch >= IC_BB && ch <= IC_BBT_1) || (ch >= IC_BAT_1 && ch <= IC_BBT_2) || (ch >= IC_BAT_2 && ch <= IC_BBT_3) || (ch >= IC_BAT_3 && ch <= IC_BA)
+    }
+    
+    private static func getPalindrom(str: String) -> String {
+        let arr: [Character] = Array(str)
+        var arr2: [Character] = Array(arr)
+
+        for i in 0..<arr.count {
+            arr2[i] = arr[arr.count - (i + 1)]
+        }
+        return String(arr2)
+    }
+    
+    private static func getBeforeChar(ch: Character, inc: Int) -> Character {
+        if icIGNORE.isEmpty {
+            initIcIgnore()
+        }
+        var iAscii = ch
+        let iAsciiBefore = iAscii
+
+        if (icIGNORE.contains(Int(iAscii.asciiValue ?? 0))) {
+            return iAscii;
+        }
+
+        if Int(iAscii.asciiValue ?? 0) > I_BA || Int(iAscii.asciiValue ?? 0) < I_BB {
+        } else {
+            if !icIGNORE.contains(Int(iAscii.asciiValue ?? 0)) {
+                iAscii = Character(UnicodeScalar(Int(iAscii.asciiValue ?? 0) - inc)!)
+                if (I_BAT_1 > Int(iAscii.asciiValue ?? 0) && Int(iAsciiBefore.asciiValue ?? 0) >= I_BAT_1) {
+                    iAscii = Character(UnicodeScalar((I_BBT_1 + 1) - (I_BAT_1 - Int(iAscii.asciiValue ?? 0)))!)
+                }
+                if (I_BAT_2 > Int(iAscii.asciiValue ?? 0) && Int(iAsciiBefore.asciiValue ?? 0) >= I_BAT_2) {
+                    iAscii = Character(UnicodeScalar((I_BBT_2 + 1) - (I_BAT_2 - Int(iAscii.asciiValue ?? 0)))!)
+                }
+                if (Int(iAscii.asciiValue ?? 0) < I_BB) {
+                    iAscii = Character(UnicodeScalar((I_BA + 1) + (Int(iAscii.asciiValue ?? 0) - I_BB))!)
+                }
+            }
+        }
+        return iAscii
+    }
+    
+    private static func getBeforecChar(ch: Character, inc: Int) -> Character {
+        var iAscii = ch
+        let iAsciiBefore = iAscii
+        if (Int(iAscii.asciiValue ?? 0) > IC_BA || Int(iAscii.asciiValue ?? 0) < IC_BB) {
+        } else {
+            iAscii = Character(UnicodeScalar(Int(iAscii.asciiValue ?? 0) - inc)!)
+            if (Int(iAscii.asciiValue ?? 0) < IC_BB) {
+                iAscii = Character(UnicodeScalar((IC_BA + 1) + (Int(iAscii.asciiValue ?? 0) - IC_BB))!)
+                if (Int(iAscii.asciiValue ?? 0) < IC_BAT_3 && Int(iAscii.asciiValue ?? 0) > IC_BBT_3) {
+                    iAscii = Character(UnicodeScalar((IC_BBT_3 + 1) - (IC_BAT_3 - Int(iAscii.asciiValue ?? 0)))!)
+                }
+            }
+            if (IC_BAT_3 > Int(iAscii.asciiValue ?? 0) && Int(iAsciiBefore.asciiValue ?? 0) >= IC_BAT_3) {
+                iAscii = Character(UnicodeScalar((IC_BBT_3 + 1) - (IC_BAT_3 - Int(iAscii.asciiValue ?? 0)))!)
+            }
+            if (IC_BAT_2 > Int(iAscii.asciiValue ?? 0) && Int(iAsciiBefore.asciiValue ?? 0) >= IC_BAT_2) {
+                iAscii = Character(UnicodeScalar((IC_BBT_2 + 1) - (IC_BAT_2 - Int(iAscii.asciiValue ?? 0)))!)
+            }
+            if (IC_BAT_1 > Int(iAscii.asciiValue ?? 0) && Int(iAsciiBefore.asciiValue ?? 0) >= IC_BAT_1) {
+                iAscii = Character(UnicodeScalar((IC_BBT_1 + 1) - (IC_BAT_1 - Int(iAscii.asciiValue ?? 0)))!)
+            }
+        }
+        return iAscii
+    }
 }
 public extension UIImage {
     var jpeg: Data? { jpegData(compressionQuality: 1) }  // QUALITY min = 0 / max = 1

+ 1 - 1
appbuilder-ios/DigiXLite/DigiXLite/Source/View/BNIView/BNIBookingWebView.swift

@@ -22,7 +22,7 @@ class BNIBookingWebView: UIViewController, WKNavigationDelegate, UIScrollViewDel
         
         let configuration = WKWebViewConfiguration()
         configuration.allowsInlineMediaPlayback = true
-        let customUserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 Safari/604.1 easySoftIndonesia"
+        let customUserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 Safari/604.1 \(Utils.getUserAgent())"
         let finalUserAgent = "\(customUserAgent)"
         configuration.applicationNameForUserAgent = finalUserAgent
         webView = WKWebView(frame: .zero, configuration: configuration)

+ 1 - 1
appbuilder-ios/DigiXLite/DigiXLite/Source/View/Chat/ChatGPTBotView.swift

@@ -12,7 +12,7 @@ import nuSDKService
 
 class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
     
-    let CHATGPT_URL = "https://DigiX.io:8439/gpt"
+    let CHATGPT_URL = "https://Nexilis.io:8439/gpt"
     
     public var dataPerson : [String: String?] = [
         "f_pin" : "-997",

+ 1 - 1
appbuilder-ios/NexilisLite/NexilisLite/Source/Download.swift

@@ -23,7 +23,7 @@ public class Download {
     
     var DOWNLOAD_BUFFER = [Data?]()
     var DOWNLOAD_SESSION = [Session]()
-    var DOWNLOAD_URL = Utils.getURLBase()! + "filepalio/image/"
+    var DOWNLOAD_URL = Utils.getURLBase() + "filepalio/image/"
     
     public func start(forKey: String, delegate: DownloadDelegate){
         self.delegate = delegate

+ 1 - 1
appbuilder-ios/NexilisLite/NexilisLite/Source/Extension.swift

@@ -346,7 +346,7 @@ extension NSObject {
 extension URL {
     
     static func palioImage(named: String) -> URL? {
-        return URL(string: Utils.getURLBase()! + "filepalio/image/\(named)")
+        return URL(string: Utils.getURLBase() + "filepalio/image/\(named)")
     }
     
 }

+ 1 - 1
appbuilder-ios/NexilisLite/NexilisLite/Source/FloatingButton/FloatingButton.swift

@@ -295,7 +295,7 @@ public class FloatingButton: UIView {
                         newButton.heightAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB).isActive = true
                         newButton.translatesAutoresizingMaskIntoConstraints = false
                         DispatchQueue.global().async {
-                            let data = try? Data(contentsOf: URL(string: "https://nexilis.io/dashboardv2/uploads/fb_icon/\(icon)")!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
+                            let data = try? Data(contentsOf: URL(string: Utils.getURLBase() + "get_file_from_path?img=\(icon)")!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
                             DispatchQueue.main.async {
                                 if data != nil {
                                     if let image = UIImage(data: data!) {

+ 4 - 0
appbuilder-ios/NexilisLite/NexilisLite/Source/IncomingThread.swift

@@ -256,6 +256,10 @@ class IncomingThread {
                     if json[CoreMessage_TMessageKey.KEY] as! String == "fb_item_with_bg" {
                         Utils.setFBItemBg(value: json[CoreMessage_TMessageKey.VALUE] as! String)
                     }
+                    if json[CoreMessage_TMessageKey.KEY] as! String == "user_agent" {
+                        Utils.setUserAgent(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    }
+                    //print("PrefsInit : \(json)")
                 }
                 Utils.setFinishInitPrefs(value: true)
             } else {

+ 1 - 1
appbuilder-ios/NexilisLite/NexilisLite/Source/Network.swift

@@ -17,7 +17,7 @@ public class Network {
     private var isCancel = false
     private var progress = 0.0
     private var CHUNK_SIZE = 200 * 1024
-    private var UPLOAD_URL = Utils.getURLBase()! + "uploader"
+    private var UPLOAD_URL = Utils.getURLBase() + "uploader"
     
     public init() {}
     

+ 116 - 22
appbuilder-ios/NexilisLite/NexilisLite/Source/Nexilis.swift

@@ -139,32 +139,33 @@ public class Nexilis: NSObject {
             imageCache.countLimit = 100
             imageCache.totalCostLimit = 1024 * 1024 * 200
             
-            let address = Nexilis.getAddress(apiKey:apiKey)
-            if address.count == 0 {
+            let address = Nexilis.getAddressNew(apiKey:apiKey)
+//            print("ADDRESS \(address)")
+            if address.isEmpty {
                 return
             }
-            UserDefaults.standard.set(address, forKey: "address")
-            UserDefaults.standard.set(address[0], forKey: "server")
-            
+//            UserDefaults.standard.set(address, forKey: "address")
+//            UserDefaults.standard.set(address[0], forKey: "server")
+//            
             Nexilis.dispatch = DispatchGroup()
             Nexilis.dispatch?.enter()
-            var server = UserDefaults.standard.string(forKey: "server")
-            if let s = server, let a = UserDefaults.standard.stringArray(forKey: "address"), s != a[0] {
-                server = a[0]
-                UserDefaults.standard.set(server, forKey: "server")
-            }
-            var ip = ""
-            var port = 0
-            if let s = server {
-                let data = s.split(separator: ":")
-                ip = String(data[0])
-                if let p = Int(data[1]) {
-                    port = p
-                }
-            }
-            Nexilis.ADDRESS = ip
-            Nexilis.PORT = port
-            //print(API.sGetVersion())
+//            var server = UserDefaults.standard.string(forKey: "server")
+//            if let s = server, let a = UserDefaults.standard.stringArray(forKey: "address"), s != a[0] {
+//                server = a[0]
+//                UserDefaults.standard.set(server, forKey: "server")
+//            }
+//            var ip = ""
+//            var port = 0
+//            if let s = server {
+//                let data = s.split(separator: ":")
+//                ip = String(data[0])
+//                if let p = Int(data[1]) {
+//                    port = p
+//                }
+//            }
+            Nexilis.ADDRESS = address.components(separatedBy: ":")[0]
+            Nexilis.PORT = Int(address.components(separatedBy: ":")[1]) ?? 0
+//            print("IP PORT \(Nexilis.ADDRESS) <> \(Nexilis.PORT)")
             var id = ""
             if let device_id = UserDefaults.standard.string(forKey: "device_id") {
                 try API.initConnection(bSwitchIP: false, sAPIK: apiKey, aAppMain: nil, cbiI: Callback(), sTCPAddr: Nexilis.ADDRESS, nTCPPort: Nexilis.PORT, sUserID: device_id, sStartWH: "09:00")
@@ -573,6 +574,99 @@ public class Nexilis: NSObject {
         return result
     }
     
+    static func getAddressNew(apiKey: String) -> String {
+        var result = ""
+        
+        if !Utils.getHarcodedIp().isEmpty {
+            result = Utils.getHarcodedIp()
+            return result
+        }
+        
+        let url = URL(string: "\(Utils.getDomainOpr())dipp/NuN1v3rs3/Qm3r4i0/get_ip_domain?account=\(apiKey)")!
+        let urlConfig = URLSessionConfiguration.default
+        urlConfig.requestCachePolicy = .returnCacheDataElseLoad
+        urlConfig.timeoutIntervalForRequest = 10.0
+        urlConfig.timeoutIntervalForResource = 10.0
+        let semaphore = DispatchSemaphore(value: 0)
+        let task = URLSession(configuration: urlConfig).dataTask(with: url) {(data, response, error) in
+            guard let data = data,
+                let url = response?.url,
+                let httpResponse = response as? HTTPURLResponse,
+                let fields = httpResponse.allHeaderFields as? [String: String] else {
+                semaphore.signal()
+                return
+            }
+            
+            let cookies = HTTPCookie.cookies(withResponseHeaderFields: fields, for: url)
+            HTTPCookieStorage.shared.setCookies(cookies, for: url, mainDocumentURL: nil)
+
+            let dataEncode = String(data: data, encoding: .utf8)!
+//            print("dataEncode \(dataEncode.trimmingCharacters(in: .whitespacesAndNewlines))")
+//            print("decrypt \(Utils.decrypt(str: "4=sm<wmpm1ir==>wtxxl"))")
+            if !dataEncode.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
+                let dataDecodeBase64 = String(data: Data(base64Encoded: dataEncode)!, encoding: .utf8)!
+                let dataRealDecode = Utils.decrypt(str: dataDecodeBase64)
+//                print("dataRealDecode \(dataRealDecode)")
+                do {
+                    if let jsonData = dataRealDecode.data(using: .utf8), let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
+                        var newDomain = jsonObject["domain"] as! String
+                        let jsonAddress = jsonObject["address"] as! [[String: Any]]
+                        let newIp = jsonAddress[0]["ip"] as! String
+                        let newPort = jsonAddress[0]["portI"] as! String
+                        if newDomain.substring(from: newDomain.count-1, to: nil) != "/" {
+                            newDomain += "/"
+                        }
+                        if (newIp+":"+newPort) != Utils.getIpOpr() || newDomain != Utils.getDomainOpr() {
+                            //check new domain
+                            if checkNewDomain(newDomain) {
+                                Utils.setDomainOpr(value: newDomain)
+                                Utils.setIpPortOpr(value: (newIp+":"+newPort))
+                            }
+                        }
+                    }
+                } catch {
+                    
+                }
+            }
+            semaphore.signal()
+        }
+        task.resume()
+        _ = semaphore.wait(timeout: .distantFuture)
+        result = Utils.getIpOpr()
+        //print("[App] getAddress:", result)
+        return result
+    }
+    
+    private static func checkNewDomain(_ newDomain: String) -> Bool {
+        var result = false
+        let url = URL(string: "\(newDomain)dipp/NuN1v3rs3/Qm3r4i0/get_ip_domain?account=\(Nexilis.sAPIKey)")!
+        let urlConfig = URLSessionConfiguration.default
+        urlConfig.requestCachePolicy = .returnCacheDataElseLoad
+        urlConfig.timeoutIntervalForRequest = 10.0
+        urlConfig.timeoutIntervalForResource = 10.0
+        let semaphore = DispatchSemaphore(value: 0)
+        let task = URLSession(configuration: urlConfig).dataTask(with: url) {(data, response, error) in
+            if let httpResponse = response as? HTTPURLResponse {
+                if httpResponse.statusCode == 200 {
+                    guard let url = response?.url,
+                        let fields = httpResponse.allHeaderFields as? [String: String] else {
+                        semaphore.signal()
+                        return
+                    }
+                    
+                    let cookies = HTTPCookie.cookies(withResponseHeaderFields: fields, for: url)
+                    HTTPCookieStorage.shared.setCookies(cookies, for: url, mainDocumentURL: nil)
+                    
+                    result = true
+                }
+            }
+            semaphore.signal()
+        }
+        task.resume()
+        _ = semaphore.wait(timeout: .distantFuture)
+        return result
+    }
+    
     static func getCLMUserId() -> String {
         guard let me = UserDefaults.standard.string(forKey: "me") else {
             return ""

+ 159 - 4
appbuilder-ios/NexilisLite/NexilisLite/Source/Utils.swift

@@ -59,7 +59,7 @@ public final class Utils {
     }
     
     static func getIconCenterAnim2() -> String? {
-        UserDefaults.standard.string(forKey: "pb_fb_icon_center_self_mode2") ?? "https://nexilis.io/dashboardv2/uploads/logofloat/525_411217560576.gif"
+        UserDefaults.standard.string(forKey: "pb_fb_icon_center_self_mode2") ?? Utils.getURLBase() + "get_file_from_path?img=525_411217560576.gif"
     }
     
     static func setIconCenterAnim4(value: String){
@@ -67,7 +67,7 @@ public final class Utils {
     }
     
     static func getIconCenterAnim4() -> String? {
-        UserDefaults.standard.string(forKey: "pb_fb_icon_center_self_mode4") ?? "https://nexilis.io/dashboardv2/uploads/logofloat/semut1.gif"
+        UserDefaults.standard.string(forKey: "pb_fb_icon_center_self_mode4") ?? Utils.getURLBase() + "get_file_from_path?img=semut1.gif"
     }
     
     static func setURLFirstTab(value: String) {
@@ -225,7 +225,7 @@ public final class Utils {
         }
     }
     
-    static func getURLBase() -> String? {
+    static func getURLBase() -> String {
         return UserDefaults.standard.string(forKey: "app_builder_url_base") ?? "https://nexilis.io/"
     }
     
@@ -234,7 +234,7 @@ public final class Utils {
     }
     
     static func getUrlDock() -> String? {
-        return Utils.getURLBase()! + "dashboardv2/uploads/logofloat/" + Utils.getIconDock()
+        return Utils.getURLBase() + "get_file_from_path?img=" + Utils.getIconDock()
     }
     
     static func setDefaultCC(value: String){
@@ -269,7 +269,162 @@ public final class Utils {
         return UserDefaults.standard.string(forKey: "fb_item_with_bg") ?? "1"
     }
     
+    static func setDomainOpr(value: String){
+        UserDefaults.standard.set(value, forKey: "domain_opr")
+    }
+    
+    static func getDomainOpr() -> String {
+        return UserDefaults.standard.string(forKey: "domain_opr") ?? "https://nexilis.io/"
+    }
+    
+    static func setIpPortOpr(value: String){
+        UserDefaults.standard.set(value, forKey: "ip_opr")
+    }
+    
+    static func getIpOpr() -> String {
+        return UserDefaults.standard.string(forKey: "ip_opr") ?? "34.101.172.194:42823"
+    }
+    
+    static func setHarcodedIp(value: String){
+        UserDefaults.standard.set(value, forKey: "harcoded_ip")
+    }
+    
+    static func getHarcodedIp() -> String {
+        return UserDefaults.standard.string(forKey: "harcoded_ip") ?? ""
+    }
+    
+    static func setUserAgent(value: String){
+        UserDefaults.standard.set(value, forKey: "user_agent")
+    }
+    
+    public static func getUserAgent() -> String {
+        return UserDefaults.standard.string(forKey: "user_agent") ?? "easySoftIndonesia"
+    }
+    
+    public static func fetchDataWithCookiesAndUserAgent(from url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> ()) {
+        var request = URLRequest(url: url)
+        request.httpMethod = "GET"
+        request.setValue(Utils.getUserAgent(), forHTTPHeaderField: "User-Agent")
+        let cookies = HTTPCookieStorage.shared.cookies ?? []
+        if let cookieHeader = HTTPCookie.requestHeaderFields(with: cookies)["Cookie"] {
+//            print("listCookiee: \(cookieHeader)")
+            request.setValue(cookieHeader, forHTTPHeaderField: "Cookie")
+        }
+        let task = URLSession.shared.dataTask(with: request, completionHandler: completion)
+        task.resume()
+    }
+    
     public static var inTabChats = false
+    
+    private static let I_BB = 48   // 0
+    private static let I_BBT_1 = 57 // 9
+    private static let I_BAT_1 = 65 // A
+    private static let I_BBT_2 = 90 // Z
+    private static let I_BAT_2 = 97 // a
+    private static let I_BA = 122  // z
+
+    private static let IC_BB = 33   // !
+    private static let IC_BBT_1 = 47 // /
+    private static let IC_BAT_1 = 58 // :
+    private static let IC_BBT_2 = 64 // @
+    private static let IC_BAT_2 = 91 // [
+    private static let IC_BBT_3 = 96 // @
+    private static let IC_BAT_3 = 123 // [
+    private static let IC_BA = 126  // `
+
+    private static var icIGNORE = Set<Int>()
+
+    private static func initIcIgnore() {
+        icIGNORE.insert(10)// \r
+        icIGNORE.insert(13)// \n
+        icIGNORE.insert(32)// <space>
+    }
+    
+    public static func decrypt(str: String) -> String {
+        var arr: [Character]
+        var iRandom = 0
+        var sDecrypt: String
+        iRandom = Int(str.substring(from: 0, to: 0)) ?? 0
+        sDecrypt = getPalindrom(str: str.substring(from: 1, to: nil))
+        arr = Array(sDecrypt)
+        for i in 0..<arr.count {
+            if (isSpecialChar(ch: arr[i])) {
+                arr[i] = getBeforecChar(ch: arr[i], inc: iRandom)
+            } else {
+                arr[i] = getBeforeChar(ch: arr[i], inc: iRandom)
+            }
+        }
+        return String(arr)
+    }
+    
+    private static func isSpecialChar(ch: Character) -> Bool {
+        let ch = Int(ch.asciiValue ?? 0)
+        return (ch >= IC_BB && ch <= IC_BBT_1) || (ch >= IC_BAT_1 && ch <= IC_BBT_2) || (ch >= IC_BAT_2 && ch <= IC_BBT_3) || (ch >= IC_BAT_3 && ch <= IC_BA)
+    }
+    
+    private static func getPalindrom(str: String) -> String {
+        let arr: [Character] = Array(str)
+        var arr2: [Character] = Array(arr)
+
+        for i in 0..<arr.count {
+            arr2[i] = arr[arr.count - (i + 1)]
+        }
+        return String(arr2)
+    }
+    
+    private static func getBeforeChar(ch: Character, inc: Int) -> Character {
+        if icIGNORE.isEmpty {
+            initIcIgnore()
+        }
+        var iAscii = ch
+        let iAsciiBefore = iAscii
+
+        if (icIGNORE.contains(Int(iAscii.asciiValue ?? 0))) {
+            return iAscii;
+        }
+
+        if Int(iAscii.asciiValue ?? 0) > I_BA || Int(iAscii.asciiValue ?? 0) < I_BB {
+        } else {
+            if !icIGNORE.contains(Int(iAscii.asciiValue ?? 0)) {
+                iAscii = Character(UnicodeScalar(Int(iAscii.asciiValue ?? 0) - inc)!)
+                if (I_BAT_1 > Int(iAscii.asciiValue ?? 0) && Int(iAsciiBefore.asciiValue ?? 0) >= I_BAT_1) {
+                    iAscii = Character(UnicodeScalar((I_BBT_1 + 1) - (I_BAT_1 - Int(iAscii.asciiValue ?? 0)))!)
+                }
+                if (I_BAT_2 > Int(iAscii.asciiValue ?? 0) && Int(iAsciiBefore.asciiValue ?? 0) >= I_BAT_2) {
+                    iAscii = Character(UnicodeScalar((I_BBT_2 + 1) - (I_BAT_2 - Int(iAscii.asciiValue ?? 0)))!)
+                }
+                if (Int(iAscii.asciiValue ?? 0) < I_BB) {
+                    iAscii = Character(UnicodeScalar((I_BA + 1) + (Int(iAscii.asciiValue ?? 0) - I_BB))!)
+                }
+            }
+        }
+        return iAscii
+    }
+    
+    private static func getBeforecChar(ch: Character, inc: Int) -> Character {
+        var iAscii = ch
+        let iAsciiBefore = iAscii
+        if (Int(iAscii.asciiValue ?? 0) > IC_BA || Int(iAscii.asciiValue ?? 0) < IC_BB) {
+        } else {
+            iAscii = Character(UnicodeScalar(Int(iAscii.asciiValue ?? 0) - inc)!)
+            if (Int(iAscii.asciiValue ?? 0) < IC_BB) {
+                iAscii = Character(UnicodeScalar((IC_BA + 1) + (Int(iAscii.asciiValue ?? 0) - IC_BB))!)
+                if (Int(iAscii.asciiValue ?? 0) < IC_BAT_3 && Int(iAscii.asciiValue ?? 0) > IC_BBT_3) {
+                    iAscii = Character(UnicodeScalar((IC_BBT_3 + 1) - (IC_BAT_3 - Int(iAscii.asciiValue ?? 0)))!)
+                }
+            }
+            if (IC_BAT_3 > Int(iAscii.asciiValue ?? 0) && Int(iAsciiBefore.asciiValue ?? 0) >= IC_BAT_3) {
+                iAscii = Character(UnicodeScalar((IC_BBT_3 + 1) - (IC_BAT_3 - Int(iAscii.asciiValue ?? 0)))!)
+            }
+            if (IC_BAT_2 > Int(iAscii.asciiValue ?? 0) && Int(iAsciiBefore.asciiValue ?? 0) >= IC_BAT_2) {
+                iAscii = Character(UnicodeScalar((IC_BBT_2 + 1) - (IC_BAT_2 - Int(iAscii.asciiValue ?? 0)))!)
+            }
+            if (IC_BAT_1 > Int(iAscii.asciiValue ?? 0) && Int(iAsciiBefore.asciiValue ?? 0) >= IC_BAT_1) {
+                iAscii = Character(UnicodeScalar((IC_BBT_1 + 1) - (IC_BAT_1 - Int(iAscii.asciiValue ?? 0)))!)
+            }
+        }
+        return iAscii
+    }
 }
 public extension UIImage {
     var jpeg: Data? { jpegData(compressionQuality: 1) }  // QUALITY min = 0 / max = 1

+ 1 - 1
appbuilder-ios/NexilisLite/NexilisLite/Source/View/BNIView/BNIBookingWebView.swift

@@ -22,7 +22,7 @@ class BNIBookingWebView: UIViewController, WKNavigationDelegate, UIScrollViewDel
         
         let configuration = WKWebViewConfiguration()
         configuration.allowsInlineMediaPlayback = true
-        let customUserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 Safari/604.1 easySoftIndonesia"
+        let customUserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 Safari/604.1 \(Utils.getUserAgent())"
         let finalUserAgent = "\(customUserAgent)"
         configuration.applicationNameForUserAgent = finalUserAgent
         webView = WKWebView(frame: .zero, configuration: configuration)