DomainDig/Models.swift

ede15c586af71b8d6f2c190ffdad0324414cac06
domain-dig/DomainDig/Models.swift history · blame · raw

187 lines · 5238 bytes

  1import Foundation
  2
  3// MARK: - DNS Models
  4
  5enum DNSRecordType: String, CaseIterable, Codable {
  6    case A
  7    case AAAA
  8    case MX
  9    case NS
 10    case TXT
 11    case CNAME
 12
 13    var queryType: Int {
 14        switch self {
 15        case .A: return 1
 16        case .AAAA: return 28
 17        case .MX: return 15
 18        case .NS: return 2
 19        case .TXT: return 16
 20        case .CNAME: return 5
 21        }
 22    }
 23}
 24
 25struct DNSRecord: Identifiable, Codable {
 26    var id = UUID()
 27    let value: String
 28    let ttl: Int
 29}
 30
 31struct DNSSection: Identifiable, Codable {
 32    var id = UUID()
 33    let recordType: DNSRecordType
 34    var records: [DNSRecord]
 35    var wildcardRecords: [DNSRecord] = []
 36    var error: String?
 37}
 38
 39// MARK: - SSL Models
 40
 41struct SSLCertificateInfo: Codable {
 42    let commonName: String
 43    let subjectAltNames: [String]
 44    let issuer: String
 45    let validFrom: Date
 46    let validUntil: Date
 47    let daysUntilExpiry: Int
 48    let chainDepth: Int
 49}
 50
 51// MARK: - HTTP Headers Models
 52
 53struct HTTPHeader: Identifiable, Codable {
 54    var id = UUID()
 55    let name: String
 56    let value: String
 57
 58    static let securityHeaders: Set<String> = [
 59        "strict-transport-security",
 60        "x-frame-options",
 61        "x-content-type-options",
 62        "content-security-policy",
 63        "referrer-policy"
 64    ]
 65
 66    var isSecurityHeader: Bool {
 67        Self.securityHeaders.contains(name.lowercased())
 68    }
 69}
 70
 71// MARK: - Reachability Models
 72
 73struct PortReachability: Identifiable, Codable {
 74    var id = UUID()
 75    let port: UInt16
 76    let reachable: Bool
 77    let latencyMs: Int?
 78}
 79
 80// MARK: - IP Geolocation Models
 81
 82struct IPGeolocation: Codable {
 83    let ip: String
 84    let city: String?
 85    let region: String?
 86    let country_name: String?
 87    let org: String?
 88    let latitude: Double?
 89    let longitude: Double?
 90}
 91
 92// MARK: - Email Security Models
 93
 94struct EmailSecurityResult: Codable {
 95    let spf: EmailSecurityRecord
 96    let dmarc: EmailSecurityRecord
 97    let dkim: EmailSecurityRecord
 98}
 99
100struct EmailSecurityRecord: Codable {
101    let found: Bool
102    let value: String?
103}
104
105// MARK: - Redirect Chain Models
106
107struct RedirectHop: Identifiable, Codable {
108    var id = UUID()
109    let stepNumber: Int
110    let statusCode: Int
111    let url: String
112    let isFinal: Bool
113}
114
115// MARK: - Port Scan Models
116
117struct PortScanResult: Identifiable, Codable {
118    var id = UUID()
119    let port: UInt16
120    let service: String
121    let open: Bool
122}
123
124// MARK: - History Models
125
126struct HistoryEntry: Identifiable, Codable {
127    var id = UUID()
128    let domain: String
129    let timestamp: Date
130    let dnsSections: [DNSSection]
131    let sslInfo: SSLCertificateInfo?
132    let httpHeaders: [HTTPHeader]
133    let reachabilityResults: [PortReachability]
134    let ipGeolocation: IPGeolocation?
135    var emailSecurity: EmailSecurityResult?
136    var ptrRecord: String?
137    var redirectChain: [RedirectHop]
138    var portScanResults: [PortScanResult]
139
140    init(domain: String, timestamp: Date, dnsSections: [DNSSection],
141         sslInfo: SSLCertificateInfo?, httpHeaders: [HTTPHeader],
142         reachabilityResults: [PortReachability], ipGeolocation: IPGeolocation?,
143         emailSecurity: EmailSecurityResult? = nil, ptrRecord: String? = nil,
144         redirectChain: [RedirectHop] = [], portScanResults: [PortScanResult] = []) {
145        self.domain = domain
146        self.timestamp = timestamp
147        self.dnsSections = dnsSections
148        self.sslInfo = sslInfo
149        self.httpHeaders = httpHeaders
150        self.reachabilityResults = reachabilityResults
151        self.ipGeolocation = ipGeolocation
152        self.emailSecurity = emailSecurity
153        self.ptrRecord = ptrRecord
154        self.redirectChain = redirectChain
155        self.portScanResults = portScanResults
156    }
157
158    init(from decoder: Decoder) throws {
159        let container = try decoder.container(keyedBy: CodingKeys.self)
160        id = try container.decodeIfPresent(UUID.self, forKey: .id) ?? UUID()
161        domain = try container.decode(String.self, forKey: .domain)
162        timestamp = try container.decode(Date.self, forKey: .timestamp)
163        dnsSections = try container.decode([DNSSection].self, forKey: .dnsSections)
164        sslInfo = try container.decodeIfPresent(SSLCertificateInfo.self, forKey: .sslInfo)
165        httpHeaders = try container.decode([HTTPHeader].self, forKey: .httpHeaders)
166        reachabilityResults = try container.decode([PortReachability].self, forKey: .reachabilityResults)
167        ipGeolocation = try container.decodeIfPresent(IPGeolocation.self, forKey: .ipGeolocation)
168        emailSecurity = try container.decodeIfPresent(EmailSecurityResult.self, forKey: .emailSecurity)
169        ptrRecord = try container.decodeIfPresent(String.self, forKey: .ptrRecord)
170        redirectChain = try container.decodeIfPresent([RedirectHop].self, forKey: .redirectChain) ?? []
171        portScanResults = try container.decodeIfPresent([PortScanResult].self, forKey: .portScanResults) ?? []
172    }
173}
174
175// MARK: - Cloudflare DNS-over-HTTPS Response
176
177struct CloudflareDNSResponse: Decodable {
178    let Status: Int
179    let Answer: [CloudflareDNSAnswer]?
180
181    struct CloudflareDNSAnswer: Decodable {
182        let name: String
183        let type: Int
184        let TTL: Int
185        let data: String
186    }
187}