Swift :Initializer for conditional binding must have Optional type, not 'String.SubSequence' (aka 'Substring') - swift

I'm working on a little project and I came across this error which I can't find on the Internet.
This is my code:
let bufferRecieved = String(bytesNoCopy: buffer, length: length, encoding: .utf8, freeWhenDone: true)
guard let delimiterFirstIndex = bufferRecieved?.index(of: ":")!,
let name = bufferRecieved![..<delimiterFirstIndex],
let message = bufferRecieved![delimiterFirstIndex...] else {
return nil
}
I get:
Initializer for conditional binding must have Optional type, not 'String.SubSequence' (aka 'Substring') for the two instructions
let name = bufferRecieved![..<delimiterFirstIndex],
let message = bufferRecieved![delimiterFirstIndex...]
What does this error mean and how can I fix it?

name and message aren't Optionals, so there's no need for them to be part of the conditional binding. Just put them after the guard statement:
guard let bufferRecieved = String(bytesNoCopy: buffer, length: length, encoding: .utf8, freeWhenDone: true),
let delimiterFirstIndex = bufferRecieved.index(of: ":") else {
return nil
}
let name = bufferRecieved[..<delimiterFirstIndex]
let message = bufferRecieved[delimiterFirstIndex...]
use(name, message)

Related

String Comparison giving unexpected result with data obtained via Alamofire

I am having issue with string comparison in Swift (I may wrong here).
Below is my method in which I am getting this issue.
Here is my input value.
self.callGrammerCheckAPI(ForText: """
ALSO BY STEPHEN HAWKING
A Brief History of Time
A Briefer History of Time
Black Holes and Baby Universes and Other Essays
The Illustrated A Brief History of Time
The Universe in a Nutshell
FOR CHILDREN
George's Secret Key to the Universe (with Lucy Hawking)
George's Cosmic Treasure Hunt (with Lucy Hawking)
ALSO BY LEONARD MLODINOW
A Briefer History of Time
The Drunkard's Walk: How Randomness Rules Our Lives
Euclid's Window: The Story of Geometry from Parallel Lines to Hyperspace
Feynman's Rainbow: A Search for Beauty in Physics and in Life
FOR CHILLDRAN
The Last Dinosaur (with Matt Costello)
Titanic Cat (with Matt Costello)
""")
Here is the method I am calling.
func callGrammerCheckAPI(ForText text:String) -> Void {
var valueToValidate = (text.components(separatedBy: .whitespacesAndNewlines).joined(separator: "+"))
let url = "https://montanaflynn-spellcheck.p.rapidapi.com/check/?text=\(valueToValidate)"
let headers: HTTPHeaders = [
"X-RapidAPI-Key": "3LlMwHr729mshN6RendH4kjvVp1pp1ogORZjsng5F2pBZdjsL3"
]
Alamofire.request(url, headers: headers).responseJSON { response in
print("Request: \(String(describing: response.request))") // original url request
print("Response: \(String(describing: response.response))") // http url response
print("Result: \(response.result)") // response serialization result
let attributedText = NSMutableAttributedString.init(string: text)
switch response.result{
case .success(let returnValue):
print(returnValue)
if let valueToParse = returnValue as? [String:Any]{
if let correctionsFound = valueToParse["corrections"] as? [String:Any]{
attributedText.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.black, range: NSRange.init(location: 0, length: attributedText.string.utf16.count))
for key in correctionsFound.keys{
let unwantedCharRegex = try! NSRegularExpression.init(pattern: "([(/\')])", options: NSRegularExpression.Options.caseInsensitive)
let formatedKey = unwantedCharRegex.stringByReplacingMatches(in: key, options: NSRegularExpression.MatchingOptions.reportCompletion, range: NSRange.init(location: 0, length: key.count), withTemplate: "")
let expression = "(\(formatedKey))."
let regex = try! NSRegularExpression.init(pattern: expression , options: NSRegularExpression.Options.caseInsensitive)
let matches = regex.matches(in: attributedText.string, options: NSRegularExpression.MatchingOptions.reportCompletion, range: NSRange.init(location: 0, length: attributedText.string.utf16.count))
outerloop: for result in matches{
guard let availableOptions = correctionsFound[key] as? [String] else{
return
}
let valueToFound:NSString = NSString.init(string: attributedText.string.subString(from: result.range.location, to: result.range.location+result.range.length))
for suggestion in availableOptions{
let leftValue:NSString = NSString.init(string: suggestion)
let rightValue:NSString = valueToFound
print("\(leftValue) == \(rightValue) = \(leftValue == rightValue)")
if (leftValue == rightValue) == true {
print("Continue Done")
continue outerloop
}
}
attributedText.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.red, range: result.range)
}
}
}
}
break
case .failure(let error):
print(error)
break
}
OperationQueue.main.addOperation {
self.tvReference.attributedText = attributedText
self.navigationItem.prompt = nil
}
if let json = response.result.value {
print("JSON: \(json)") // serialized json response
}
if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) {
print("Data: \(utf8Text)") // original server data as UTF8 string
}
}
}
Issue is when I compare leftValue and rightValue even though both the values are same it returns false. I do not know what went wrong there.

Upgraded from Kanna 2.2.1 to 4.0.2 and getting the same error

I am rewriting a project I found on Github to learn and teach myself how to use swift and pod files. I upgraded Kanna from 2.2.1 to 4.0.2 because I was getting an arm64 error.
With 4.0.2 I am getting the error:
Initializer for conditional binding must have Optional type, not 'HTMLDocument'
Call can throw, but it is not marked with 'try' and the error is not handled
I am unsure about what this error means and how to fix it. It is associated with this if statement:
if let doc = Kanna.HTML(html: htmlText, encoding: String.Encoding.utf8) {
for itemSize in doc.css("option[value^='']") {
let itemSizeText = itemSize.text!.lowercased()
let wishListItemSize = self.websiteInstance!.websiteWishListItem.size!.lowercased()
if itemSizeText.range(of: wishListItemSize) != nil {
print("Found size")
foundItemSize = true
let itemSizeValue = itemSize["value"]
self.websiteInstance!.viewController!.websiteBrowser!.evaluateJavaScript("document.getElementById(\"size-options\").value = \(itemSizeValue!)", completionHandler: nil)
break
}
countSize += 1
}
}
The type signature for the method you are calling is public func HTML(html: String, url: String? = nil, encoding: String.Encoding, option: ParseOption = kDefaultHtmlParseOption) throws -> HTMLDocument. The function returns a non-Optional value, but can throw an error.
You can handle the error by either using the try? keyword to make the function return nil in case an error was thrown and make the optional binding you currently use work like this:
if let doc = try? Kanna.HTML(html: htmlText, encoding: String.Encoding.utf8) {...
or rather use try and put the function call in a do-catch block to see the actual error in case any was thrown.
do {
let doc = Kanna.HTML(html: htmlText, encoding: String.Encoding.utf8)
for itemSize in doc.css("option[value^='']") {
let itemSizeText = itemSize.text!.lowercased()
let wishListItemSize = self.websiteInstance!.websiteWishListItem.size!.lowercased()
if itemSizeText.range(of: wishListItemSize) != nil {
print("Found size")
foundItemSize = true
let itemSizeValue = itemSize["value"]
self.websiteInstance!.viewController!.websiteBrowser!.evaluateJavaScript("document.getElementById(\"size-options\").value = \(itemSizeValue!)", completionHandler: nil)
break
}
countSize += 1
}
} catch {
print(error)
// Handle error
}

Error validating CMS signature

For the past 2 weeks I've been banging my head against a wall trying to create and validate CMS signatures in Swift 4 using OpenSSL. My code is ultimately destined to be run on Linux, so I can't use the macOS Security framework. I believe I have finally gotten CMS signature creation working properly. My code for that looks like this:
let testBundle = Bundle(for: type(of: self))
guard let textUrl = testBundle.url(forResource: "test_message", withExtension: "txt"),
let signingKeyUrl = testBundle.url(forResource: "signing_key", withExtension: "pem"),
let signingCertUrl = testBundle.url(forResource: "signing_cert", withExtension: "pem") else {
exit(1)
}
let certFileObject = signingCertUrl.path.withCString { filePtr in
return fopen(filePtr, "rb")
}
defer {
fclose(certFileObject)
}
let keyFileObject = signingKeyUrl.path.withCString { filePtr in
return fopen(filePtr, "rb")
}
defer {
fclose(keyFileObject)
}
guard let key = PEM_read_PrivateKey(keyFileObject, nil, nil, nil),
let cert = PEM_read_X509(certFileObject, nil, nil, nil) else {
exit(1)
}
OpenSSL_add_all_ciphers()
OpenSSL_add_all_digests()
OPENSSL_add_all_algorithms_conf()
guard let textData = FileManager.default.contents(atPath: textUrl.path) else {
exit(1)
}
guard let textBIO = BIO_new(BIO_s_mem()) else {
print("Unable to create textBIO")
exit(1)
}
_ = textData.withUnsafeBytes({dataBytes in
BIO_write(textBIO, dataBytes, Int32(textData.count))
})
guard let cms = CMS_sign(cert, key, nil, textBIO, UInt32(CMS_BINARY)) else {
exit(1)
}
When I debug this code, I see that the cms object is being set after the CMS_sign call, so I believe that the signature was generated properly. Right after this, I'm trying to validate the signature I just created. That code looks like this:
let store = X509_STORE_new()
X509_STORE_add_cert(store, cert)
let outBIO = BIO_new(BIO_s_mem())
let result = CMS_verify(cms, nil, store, nil, outBIO, 0)
print("result : \(result)")
if result != 1 {
let errorCode: UInt = ERR_get_error()
print("ERROR : \(String(format: "%2X", errorCode))")
}
When I run this code, however, result == 0, indicating an error. The error code that OpenSSL is returning is 0x2E099064. I ran this command:
openssl errstr 0x2E099064
Which gave me this info about the error:
error:2E099064:CMS routines:func(153):reason(100)
After a bit more digging, I think that the error corresponds to PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH. I got that from the pkcs7.h file here. I'm not 100% that this is the correct error message, however.
My question is, why is my signature validation failing? I'm using the exact same certificate to validate the signature. All of this code is inline, so nothing is getting lost anywhere. Can any of you give me an idea where things are going wrong?

how to add triple des encryption decryption in swift

i am very tensed last 2 days due to encryption / decryption in triple Des in swift i am follow below link but not its show error where i get libraries of CCAlgorithem and CCOptions please check below image and please help me this
Note: I'm New In Swift Xcode
how to add these library in my code i'm new in swift
import UIKit
import CryptoSwift
class CypherSwift: NSObject {
func tripleDesEncrypt(pass: String) -> String{
//help from this thread
//http://stackoverflow.com/questions/25754147/issue-using-cccrypt-commoncrypt-in-swift
let keyString = "25d1d4cb0a08403e2acbcbe0"
let keyData: NSData! = (keyString as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
let message = pass
let data: NSData! = (message as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
let cryptData = NSMutableData(length: Int(data.length) + kCCBlockSize3DES)!
let keyLength = size_t(kCCKeySize3DES)
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES)
let options: CCOptions = UInt32(kCCOptionECBMode + kCCOptionPKCS7Padding)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
keyData.bytes, keyLength,
nil,
data.bytes, data.length,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
// Not all data is a UTF-8 string so Base64 is used
var base64cryptString = cryptData.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
print("base64cryptString = \(base64cryptString)")
base64cryptString = base64cryptString + "\n"
return encodeString(base64cryptString)
} else {
print("Error: \(cryptStatus)")
}
return ""
}
func encodeString(str: String) -> String{
let customAllowedSet = NSCharacterSet(charactersInString:"==\n").invertedSet
let escapedString = str.stringByAddingPercentEncodingWithAllowedCharacters(customAllowedSet)
print("escapedString: \(escapedString)")
return escapedString!
}
}
image of error
tiple des link 1
triple des link 2
Unfortunately, there's currently no pre-defined Swift module for CommonCrypto, which means that you'll either have to create one yourself in a module.modulemap file, or import it in your bridging header. If you're making an app and not a framework, the latter is the easiest: just create a bridging header (if you don't have one, just add an Objective-C source file to the project and it'll offer to create one automatically; you can delete the Objective-C source file afterwards). Next, add this to the bridging header:
#import <CommonCrypto/CommonCrypto.h>
Note that if you're making a framework, the bridging header won't work and you'll have to make a modulemap instead (let me know if this is the case, and I'll edit something into the answer).
Anyway, the above will get rid of all the errors about kCC things not being found. Now that that's done, there are still a few things in the code that need fixing.
First of all, get rid of the unnecessary use of NS classes. Change:
let keyData: NSData! = (keyString as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
to:
let keyData = keyString.data(using: .utf8)!
The ! is acceptable in this case, since we know what keyString is and we know that it's definitely always convertible to UTF-8.
Now, do the same thing for data. Unfortunately in this case, message depends on user input, so we shouldn't use !—if the message turns out not to be convertible to UTF-8, ! will cause your app to crash, which usually isn't what you want. It's better to use guard let and then bail if the conversion fails, either by making your function's return value optional and returning nil or adding throws to your function's return value and throwing an error:
guard let data = message.data(using: .utf8) else {
return nil
OR:
throw CocoaError(.fileReadInapplicableStringEncoding) // or some custom error
}
The next issue is the use of bytes on your Data object. In Swift, this is not allowed, because it's unsafe; if the Data is deallocated before you're done with bytes, you'll crash or run into other weird behavior. Instead, you should use withUnsafeBytes, and do the work requiring the bytes inside a closure. This is safer, since the Data is guaranteed to be valid at least until the closure returns. Since we have three separate Datas that we need the bytes of, this is kind of unwieldy with a triple-nested closure, but we can do it:
let cryptStatus = keyData.withUnsafeBytes { (keyBytes: UnsafePointer<UInt8>) in
data.withUnsafeBytes { (dataBytes: UnsafePointer<UInt8>) in
cryptData.withUnsafeMutableBytes { (cryptBytes: UnsafeMutablePointer<UInt8>) in
CCCrypt(operation,
algoritm,
options,
keyBytes,
keyLength,
nil,
dataBytes,
data.count,
cryptBytes,
cryptData.count,
&numBytesEncrypted)
}
}
}
After that, you've just got some more Objective-C-isms to make properly Swifty, and your encrypt function should be done:
cryptData.count = Int(numBytesEncrypted)
// Not all data is a UTF-8 string so Base64 is used
var base64cryptString = cryptData.base64EncodedString(options: .lineLength64Characters)
The only problem I see in the encode function is a few Objective-C-isms that you should modernize:
let customAllowedSet = CharacterSet(charactersIn: "==\n").inverted
let escapedString = str.addingPercentEncoding(withAllowedCharacters: customAllowedSet)
There's also the calling convention of your encode function; func encodeString(str: String) means you'll have to call it like return encodeString(str: base64cryptString) with the label present. If you want to call it without the label, you can change the signature to func encodeString(_ str: String).

How to initialize a MLMultiArray in CoreML

I've got an array of 40 arrays with 12 double features, so the type is [[double]]. Currently I'm sending this data to Google Cloud ML API to get a related prediction.
Since Apple recently introduced CoreML and coremltools, I converted my model from keras to .mlmodel to avoid thousand of google cloud api calls and do inference directly on my iPhone:
coreml_model = coremltools.converters.keras.convert(new_Model, input_names=['accelerations'],
output_names=['scores'])
coreml_model.save('PredictionModel.mlmodel')
After adding the model to my Xcode Project, it looks like:
I have no idea, where these others inputs and outputs are comming from.
To get a prediction, I need to convert my Array of Arrays of 12 doubles to an MLMultiArray, but I don't know how to do this. Has anyone faced a similar problem? Here is my current unfinished approach:
_predictionModel = PredictionModel()
guard let mlMultiArray = try? MLMultiArray(dataPointer: <#T##UnsafeMutableRawPointer#>, shape: <#T##[NSNumber]#>, dataType: <#T##MLMultiArrayDataType#>, strides: <#T##[NSNumber]#>, deallocator: <#T##((UnsafeMutableRawPointer) -> Void)?##((UnsafeMutableRawPointer) -> Void)?##(UnsafeMutableRawPointer) -> Void#>) else {
fatalError("Unexpected runtime error.")
}
guard let predictionOutput = try? _predictionModel.prediction(accelerations: mlMultiArray, lstm_1_h_in: nil, lstm_1_c_in: nil, lstm_2_h_in: nil, lstm_2_c_in: nil) else {
fatalError("Unexpected runtime error.")
}
The related documentation can be found here.
I achieved it by reading this blog :)
let data = _currentScaledMotionArrays.reduce([], +) //result is of type [Double] with 480 elements
guard let mlMultiArray = try? MLMultiArray(shape:[40,12], dataType:MLMultiArrayDataType.double) else {
fatalError("Unexpected runtime error. MLMultiArray")
}
for (index, element) in data.enumerated() {
mlMultiArray[index] = NSNumber(floatLiteral: element)
}
let input = PredictionModelInput(accelerations: mlMultiArray)
guard let predictionOutput = try? _predictionModel.prediction(input: input) else {
fatalError("Unexpected runtime error. model.prediction")
}
This is how I did it. Probably not the best way to handle optionals but gets the job done for testing
Create an instance of the MLMultiArray object with shape and data type
let mlArray = try? MLMultiArray(shape: [3], dataType: MLMultiArrayDataType.float32)
mlArray does not have an append function so you literally have to iterate through it and add values
for i in 0..<array.count {
mlArray?[i] = NSNumber(value: input[i])
}
Full function
func convertToMLArray(_ input: [Int]) -> MLMultiArray {
let mlArray = try? MLMultiArray(shape: [3], dataType: MLMultiArrayDataType.float32)
for i in 0..<array.count {
mlArray?[i] = NSNumber(value: input[i])
}
return arr!
}