diff --git a/enzevalos_iphone/StringExtension.swift b/enzevalos_iphone/StringExtension.swift index 4d06992f15aaa5e970cd1c8b9ec01f8c556531b0..c3806413ba900a87b3f4920570da7a17de9f65ac 100644 --- a/enzevalos_iphone/StringExtension.swift +++ b/enzevalos_iphone/StringExtension.swift @@ -64,6 +64,37 @@ extension String { } } +extension String { + /** + Returns true if a String contains upper case letters. + */ + func containsUpperCaseLetter() -> Bool { + let url = self + let regEx = "[A-Z]" + let range = NSRange(location: 0, length: url.utf16.count) + let regex = try! NSRegularExpression(pattern: regEx) + if regex.firstMatch(in: url, options:[], range: range) != nil { + return true + } + return false + } + + /** + Returns true if the string contains two or more consecutive dots + */ + func twoDotsOrMore() -> Bool { + let url = self + // Finds 2 or more consecutive dots + let regEx = "\\.{2,}" + let range = NSRange(location: 0, length: url.utf16.count) + let regex = try! NSRegularExpression(pattern: regEx) + if regex.firstMatch(in: url, options:[], range: range) != nil { + return true + } + return false + } +} + /** functions to split an emailadress into their domains */ @@ -141,7 +172,6 @@ Functions to find E-mail adresses and URLs extension String { func isValidEmail() -> Bool { - let emailRegEx = "(?!\\u10000-\\uEFFFF.*\\.\\.)([^@\\s]{2,64}+@[^@\\s]+\\.[^@\\s\\.]+$)" let emailTest = NSPredicate(format:"SELF MATCHES %@", emailRegEx) return emailTest.evaluate(with: self) @@ -193,21 +223,6 @@ extension String { return(results) } - /** - Returns true if the string contains two or more consecutive dots - */ - func twoDotsOrMore() -> Bool { - let url = self - // Finds 2 or more consecutive dots - let regEx = "\\.{2,}" - let range = NSRange(location: 0, length: url.utf16.count) - let regex = try! NSRegularExpression(pattern: regEx) - if regex.firstMatch(in: url, options:[], range: range) != nil { - return true - } - return false - } - /** For text only, not for hyperlink detection Returns URLs from a given String @@ -354,239 +369,6 @@ extension String { } } -/** -Functions to validate URLs and Email adresses -*/ -extension String { - - /** - Compares a String with a list of strings and checks whether the edit distance between them is in the allowed range. - Returns a boolean value and a list of strings that had an un-allowed edit distance with the original string - The Bool values is returned False: if the string has an un-allowed edit distance with any other element from the list. - */ - func compareWith(strings: [String], allowedEditDistance: Int) -> (Bool, [String]) { - var isAllowedEditDistance = true - var strList: [String] = [] - for str in strings { - if !self.isAllowedDistance(str: str, allowedEditDistance: allowedEditDistance) { - isAllowedEditDistance = false - strList.append(str) - } - } - return (isAllowedEditDistance, strList) - } - - /** - Compares a url's root domain with all root domain of all elements in a given url list. - false: if the URL's root domain has an unallowed edit distance with any other root domain. - */ - func compareURLs(urls: [String]) -> Bool { - let rootDomain = self.getRootDomain() - var isAllowedEditDistance = true - for url in urls { - let rd = url.getRootDomain() - if !rootDomain.isAllowedDistance(str: rd, allowedEditDistance: 4) { - // 2 domains contain less than 4 differences --> warning here needed - print("Warning!! \n Edit distance is not in the allowed range between link: " + self + " and link: " + url) - isAllowedEditDistance = false - } - } - return isAllowedEditDistance - } - - /** - Compares a url's root domain with all root domain of all elements in a given url list. - Returns an dictionary with the urls as the keys and and a bollean if it fits the allowed editdistance as value - isAllowedDistance is false: if the URL's root domain has an unallowed edit distance with any other root domain. - */ - func compareURLsDic(urls: [String]) -> [String:String] { - let rootDomain = self.getRootDomain() - var isAllowedEditDistance = true - var typoDic: [String:String] = [:] - for url in urls { - let rd = url.getRootDomain() - if !rootDomain.isAllowedDistance(str: rd, allowedEditDistance: 4) { - // 2 domains contain less than 4 differences --> warning here needed - print("Warning!! \n Edit distance is not in the allowed range between link: " + self + " and link: " + url) - isAllowedEditDistance = false - typoDic.updateValue(String(isAllowedEditDistance), forKey : url) - isAllowedEditDistance = true - } - else{ - typoDic.updateValue(String(isAllowedEditDistance), forKey : url) - } - } - return typoDic - } - - /** - Compares a url's root domain with all root domain of all elements in a givin url list. - Retruns an dictionary with the URLs as keys and the Editdistance as value - */ - func getURLEditdistance(urls: [String]) -> [String:String] { - let rootDomain = self.getRootDomain() - var urlEditDic: [String:String] = [:] - var editDistance = 0 - for url in urls { - let rd = url.getRootDomain() - editDistance = rootDomain.getEditDistance(str: rd) - urlEditDic.updateValue(String(editDistance), forKey : url) - } - return urlEditDic - } - - /** - Compares a URLs second-level domain with all elements of a givin domain list. - false: if the URL's second-level domain has an unallowed edit distance with any other domain. - */ - func compareURLWithSLDList(domains: [String]) -> Bool { - let secondLevelDomain = self.getSecondLevelDomain() - var isAllowedEditDistance = true - for domain in domains { - if !secondLevelDomain.isAllowedDistance(str: domain, allowedEditDistance: 4) { - // 2 domains contain less than 4 differences --> warning here needed - print("Warning!! \n Edit distance is not in the allowed range between domain: " + secondLevelDomain + " and domain: " + domain) - isAllowedEditDistance = false - } - } - return isAllowedEditDistance - } - - /** - Compares a url's second level domain with all domains of all elements in a givin url list. - Returns an dictionary with the domains as the keys and and a bollean if it fits the allowed editdistance as value - isAllowedDistance is false: if the URL's second level domain has an unallowed edit distance with any other domain. - */ - func compareURLWithSLDListDic(domains: [String]) -> [String:String] { - let secondLevelDomain = self.getSecondLevelDomain() - var isAllowedEditDistance = true - var typoDic: [String:String] = [:] - for domain in domains { - if !secondLevelDomain.isAllowedDistance(str: domain, allowedEditDistance: 4) { - // 2 domains contain less than 4 differences --> warning here needed - print("Warning!! \n Edit distance is not in the allowed range between link: " + self + " and link: " + domain) - isAllowedEditDistance = false - typoDic.updateValue(String(isAllowedEditDistance), forKey : domain) - isAllowedEditDistance = true - } - else{ - typoDic.updateValue(String(isAllowedEditDistance), forKey : domain) - } - } - return typoDic - } - - /** - Compares a url's second-level domain with all elements of a givin domain list. - Retruns an dictionary with the second level domain as keys and the editdistance as value - */ - func getSLDEditdistance(domains: [String]) -> [String:String] { - let secondLevelDomain = self.getSecondLevelDomain() - var sldEditDic: [String:String] = [:] - var editDistance = 0 - for domain in domains { - editDistance = secondLevelDomain.getEditDistance(str: domain) - sldEditDic.updateValue(String(editDistance), forKey : domain) - } - return sldEditDic - } - - /** - Compares a second-level domain with all elements of a givin second-level domain list. - false: if the second-level domain has an unallowed edit distance with any other domain. - */ - func compareDomainWithDomians(domains: [String]) -> Bool { - var isAllowedEditDistance = true - for domain in domains { - if !self.isAllowedDistance(str: domain, allowedEditDistance: 4) { - // 2 domains contain less than 4 differences --> warning here needed - print("Warning!! \n Edit distance is not in the allowed range between domain: " + self + " and domain: " + domain) - isAllowedEditDistance = false - } - } - return isAllowedEditDistance - } - - /** - Compares a second level domain withall elements of a givin second-level domain list. - Returns an dictionary with the domains as the keys and and a bollean if it fits the allowed editdistance as value - isAllowedDistance is false: if the second level domain has an unallowed edit distance with any other domain. - */ - func compareDomainWithDomiansDic(domains: [String]) -> [String:String] { - var isAllowedEditDistance = true - var typoDic: [String:String] = [:] - for domain in domains { - if !self.isAllowedDistance(str: domain, allowedEditDistance: 4) { - // 2 domains contain less than 4 differences --> warning here needed - print("Warning!! \n Edit distance is not in the allowed range between link: " + self + " and link: " + domain) - isAllowedEditDistance = false - typoDic.updateValue(String(isAllowedEditDistance), forKey : domain) - isAllowedEditDistance = true - } - else{ - typoDic.updateValue(String(isAllowedEditDistance), forKey : domain) - } - } - return typoDic - } - - /** - Compares a domain with all elements of a givin domain list. - Retruns an dictionary with domains as keys and the editdistance as value - */ - func getDomainEditdistance(domains: [String]) -> [String:String] { - var domainEditDic: [String:String] = [:] - var editDistance = 0 - for domain in domains { - editDistance = self.getEditDistance(str: domain) - domainEditDic.updateValue(String(editDistance), forKey : domain) - } - return domainEditDic - } - - /** - Returns true if a String contains upper case letters. - */ - func containsUpperCaseLetter() -> Bool { - let url = self - let regEx = "[A-Z]" - let range = NSRange(location: 0, length: url.utf16.count) - let regex = try! NSRegularExpression(pattern: regEx) - if regex.firstMatch(in: url, options:[], range: range) != nil { - return true - } - return false - } - - /** - Returns valid Root Domain and verifys them - */ - func isValidRD() -> [String] { - let urls = self.findURL() - var foundRDs: [String] = [] - for url in urls { - let urlString: String = url! - if !urlString.containsUpperCaseLetter() { - guard let result: TLDResult = extractor.parse(urlString) else { continue } - if let rd = result.rootDomain { - let rdPatternRegEx = "^([a-z0-9])*([a-z0-9-]+\\.)*[a-z0-9]*([a-z0-9-]+)*[a-z0-9]+\\.[a-z]{2,11}?$" // for hostname - let range = NSRange(location: 0, length: rd.utf16.count) - let regex = try! NSRegularExpression(pattern: rdPatternRegEx) - if regex.firstMatch(in: rd, options:[], range: range) != nil { - foundRDs.append(rd) - } else { - // domain did not pass the regex --> warning here needed - } - } - } else { - // domain contains capital letters --> warning here needed - } - } - // Returns non-Critical Root Domain list - return (foundRDs) - } -} - /** Levenshtein Algorithm to calculate the editdistance Returns the editdistance betwenn two Strings @@ -626,6 +408,23 @@ extension String { } return true } + + /** + Compares a String with a list of strings and checks whether the edit distance between them is in the allowed range. + Returns a boolean value and a list of strings that had an un-allowed edit distance with the original string + The Bool values is returned False: if the string has an un-allowed edit distance with any other element from the list. + */ + func compareWith(strings: [String], allowedEditDistance: Int) -> (Bool, [String]) { + var isAllowedEditDistance = true + var strList: [String] = [] + for str in strings { + if !self.isAllowedDistance(str: str, allowedEditDistance: allowedEditDistance) { + isAllowedEditDistance = false + strList.append(str) + } + } + return (isAllowedEditDistance, strList) + } /** Levenshtein Algorithm diff --git a/enzevalos_iphoneTests/phishing/TyposquattingTests.swift b/enzevalos_iphoneTests/phishing/TyposquattingTests.swift index 91a5fd28bdd3dbb2f11d1dd3832d3fc96cbb4202..028b9c8631ec56350fda109899865a09da43ce09 100644 --- a/enzevalos_iphoneTests/phishing/TyposquattingTests.swift +++ b/enzevalos_iphoneTests/phishing/TyposquattingTests.swift @@ -14,7 +14,7 @@ class TyposquattingTests: XCTestCase { let typosquatting = Typosquatting() - // Setup + // Setup for testcases let validRD = ["fu-berlin.de", "google.de", "nljbjkjk.de", "w3schools.com", "w2schools.com", "w8schools.com", "w33schools.com", "w22schools.com", "w99schools.eu.com", "3schools.com"] let validSLD = ["fu-berlin", "google", "nljbjkjk", "w3schools", "w2schools", "w8schools", "w33schools", "w22schools", "w99schools.eu", "3schools"] @@ -84,5 +84,4 @@ class TyposquattingTests: XCTestCase { let url = "www.w2schools.com" XCTAssertFalse(typosquatting.compareURLs(url: url, urls: validURLs)) } - }