taler-ios

iOS apps for GNU Taler (wallet)
Log | Files | Refs | README | LICENSE

URL+id+iban.swift (4179B)


      1 /*
      2  * This file is part of GNU Taler, ©2022-25 Taler Systems S.A.
      3  * See LICENSE.md
      4  */
      5 /**
      6  * @author Marc Stibane
      7  */
      8 import SwiftUI
      9 
     10 extension URL: Identifiable {
     11     public var id: URL {self}
     12 }
     13 
     14 extension URL {
     15     init(_ string: StaticString) {
     16         self.init(string: "\(string)")!
     17     }
     18 
     19     var trimmedString: String {
     20         absoluteString.trimmingCharacters(in: .whitespacesAndNewlines)
     21     }
     22 
     23     var cyclos: String? {
     24         /// "payto://cyclos/" host ["/" fpath] "/" account-id [ "?" opts ]
     25         if scheme == "payto", let host = host {
     26             let path = path.dropFirst(1)
     27             if host == "cyclos" {
     28                 return String(path)
     29             } else if host.hasPrefix("cyclos") {
     30                 let cyclos = host.dropFirst(6)
     31                 if path.hasPrefix("/") {
     32                     return String(cyclos + path)
     33                 }
     34                 return String(cyclos + "/" + path)
     35             }
     36         }
     37         return nil
     38     }
     39 
     40     var iban: String? {
     41         /// https://datatracker.ietf.org/doc/rfc8905/
     42         /// payto://iban/DE75512108001245126199?amount=EUR:200.0&message=hello
     43         if scheme == "payto" && host == "iban" {
     44             return lastPathComponent
     45         }
     46         return nil
     47     }
     48 
     49     var xTaler: String? {
     50         /// https://datatracker.ietf.org/doc/rfc8905/
     51         /// payto://x-taler-bank/BANK-HOST/ACCOUNT?receiver-name=…
     52         /// The bank host is part of the target, so return "BANK-HOST/ACCOUNT" —
     53         /// returning only lastPathComponent silently dropped the bank and made
     54         /// the account unaddressable when it was written back out.
     55         if scheme == "payto" && host == "x-taler-bank" {
     56             let target = path.hasPrefix("/") ? String(path.dropFirst()) : path
     57             return target.isEmpty ? nil : target
     58         }
     59         return nil
     60     }
     61 
     62     /// SwifterSwift: Dictionary of the URL's query parameters.
     63     var queryParameters: [String:String]? {
     64         guard let components = URLComponents(url: self, resolvingAgainstBaseURL: false),
     65               let queryItems = components.queryItems else { return nil }
     66 
     67         var items: [String:String] = [:]
     68 
     69         for queryItem in queryItems {
     70             items[queryItem.name] = queryItem.value
     71         }
     72         return items
     73     }
     74 
     75     static var docDirUrl: URL? {                    // accessible by FileSharing
     76         if #available(iOS 16.4, *) {
     77             return URL.documentsDirectory
     78         } else {
     79             let docDirNr: FileManager.SearchPathDirectory = .documentDirectory
     80             if let documentsDir = FileManager.default.urls(for: docDirNr, in: .userDomainMask).first {
     81                 return documentsDir
     82             }
     83         }
     84         return nil
     85     }
     86 
     87     static var appSuppUrl: URL? {
     88         if #available(iOS 16.4, *) {
     89             return URL.applicationSupportDirectory
     90         } else {
     91             let appDirNr: FileManager.SearchPathDirectory = .applicationSupportDirectory
     92             if let appSupportDir = FileManager.default.urls(for: appDirNr, in: .userDomainMask).first {
     93                 return appSupportDir
     94             }
     95         }
     96         return nil
     97     }
     98 
     99     static var tempDirUrl: URL? {
    100         if #available(iOS 16.4, *) {
    101             return URL.temporaryDirectory
    102         } else { // iOS 15 doesn't have a temp dir
    103             let tmpDirNr: FileManager.SearchPathDirectory = .cachesDirectory
    104             if let cachesDir = FileManager.default.urls(for: tmpDirNr, in: .userDomainMask).first {
    105                 return cachesDir
    106             }
    107         }
    108         return nil
    109     }
    110 
    111     func path(withSlash: Bool) -> String {
    112         let path: String
    113         if #available(iOS 16.4, *) {
    114             path = self.path(percentEncoded: false)
    115         } else {
    116             path = self.path
    117         }
    118         if let char = path.last {
    119             let slash: String.Element = "/"
    120 
    121             if withSlash {
    122                 if char != slash {
    123                     return path + String(slash)
    124                 }
    125             } else {
    126                 if char == slash {
    127                     return String(path.dropLast())
    128                 }
    129             }
    130         }
    131         return path
    132     }
    133 }