DomainDig/Models.swift
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}