Swift Post Special and Foreign characters - xcode

For the posting I am using
var post = "content=\(message)&post=\(time)"
But when I enter something like € for variable message, I get this error:
fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb)
When there are no special characters it works and I get back:
2015-02-04 15:38:16.918 sdfff[12306:60b] Response code: 200
2015-02-04 15:38:16.920 sdfff[12306:60b] Response ==> {"success":1}

You have to use stringByAddingPercentEscapesUsingEncoding when using special charactheres in your NSURL as follow:
var post = "content=€&post=€".stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
println(post) // "content=%E2%82%AC&post=%E2%82%AC"
var revert = "content=%E2%82%AC&post=%E2%82%AC".stringByRemovingPercentEncoding!
println(revert) // "content=€&post=€"

Related

PowerQuery: Getting error info when it's too late to `try`?

Short Version
In PowerQuery, when the error occurs before I'm able to use try, how do I catch an error and get the reason and message strings?
Long Version
In PowerQuery (using Excel if that matters),
OleDb.DataSource(
MyConnectionString,
[Query="SELECT * FROM NonExistingTable"]
)
returns an error. Great. I want that because I'm trying to make a quick and dirty tool that grabs data from multiple tables, but some people don't have access to all tables and who knows what else will happen in the future. However, I want to handle that error so it degrades gracefully, preferably presenting an explanation to the user based on the info within the error.
Therefore, I attempted error handling with try, like so:
try OleDb.DataSource(
MyConnectionString,
[Query="SELECT * FROM NonExistingTable"]
)
and I had expected it to return something like
[
HasError = true,
Error = [
Reason = "OLE DB",
Message = "Invalid object name: 'NonExistingTable'.",
Details = ...
]
]
but instead, what's returned is
[
HasError = false,
Value = Error
]
where Error is an error object containing the information I want.
I had then tried to make a workaround with something like
let
tryRecord = try OleDb.DataSource(MyConnectionString, [Query="SELECT * FROM NonExistingTable"]),
ret = if (tryRecord[HasError]) then
// It's an error
tryRecord
else try
// If Value.Type() doesn't throw an error then tryRecord[Value] isn't an error, so return it.
(if Value.Type(tryRecord[Value]) = null then null else tryRecord)
otherwise
// tryRecord[Value] contains an error!
try error tryRecord[Value]
in
ret
but try error tryRecord[Value] is not unpacking the error object within tryRecord[Value] like I had hoped.
How do I get the reason and message strings from an error object?

how to make an api call to server which requires special characters using NSURL session?

I am building an iOS app with Swift2.0, XCode 7.2
I am trying to make an api call to:
htttp://xyz.com/t/restaurants-us?KEY=someKey&filters={"locality":{"$eq":"miami"}}
let endPoint:String = "htttp://xyz.com/t/restaurants-us?KEY=someKey&filters={%22locality%22:{%22$eq%22:%22miami%22}}"
When I try to create an URL using this string(endPoint):
let url = NSURL(string: endPoint), a nil is returned.
So I tried encoding the string before trying to create URL:
let encodedString = endPoint.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())
Now the encodedString:
"htttp://xyz.com/t/restaurants-us?KEY=someKey&filters=%7B%2522locality%2522:%7B%2522$eq%2522:%2522miami%2522%7D%7D"
But now when i create a NSURL session and send the request, I get an unexpected response from the server:
Reply from server:
{
"error_type" = InvalidJsonArgument;
message = "Parameter 'filters' contains an error in its JSON syntax. For documentation, please see: http://developer.factual.com.";
status = error;
version = 3;
}
So if I don't encode the string, I will not be able to create NSURL.
But if I encode and send the request, the server is not able to handle the request.
Can anyone please suggest a workaround.
When you declare endpoint, you have already percent-encoded some characters (the quotes). When you ask iOS to percent-encode it, it percent-encodes the percent-encodes. Decoding the encodedString results in:
htttp://xyz.com/t/restaurants-us?KEY=someKey&filters={%22locality%22:{%22$eq%22:%22miami%22}}
Instead, you should start with actual quotes in endpoint:
let endPoint:String = "htttp://xyz.com/t/restaurants-us?KEY=someKey&filters={\"locality\":{\"$eq\":\"miami\"}}"

XPC Service returning NSAttributtedString

I have a huge problem to transfer NSAttributtedString in a block callback from XPC service.
I am trying to return basic string as:
NSDictionary *arrayComa = #{NSForegroundColorAttributeName:[NSColor colorWithRGB:0xD35250],
NSFontAttributeName:[NSFont fontWithName:#"Monaco" size:11]};
NSMutableAttributedString *testString = [[NSMutableAttributedString alloc] initWithString:#"{}" attributes:arrayComa];
I have also whitelisted the incoming response as:
let incommingClasses:Set = Set(arrayLiteral: [NSMutableAttributedString.self, NSAttributedString.self, NSColor.self, NSFont.self, NSString.self, ])
connectionService.remoteObjectInterface?.setClasses(incommingClasses, forSelector: attributtedText:withReply:, argumentIndex: 0, ofReply: true)
What ever I do I get Errors:
Exception caught during decoding of received reply to message 'Exception caught during decoding of received reply to message 'attributtedText:withReply':, dropping incoming message and calling failure block.
Exception: Exception while decoding argument 0 (#1 of invocation):
<NSInvocation: 0x6000006649c0>
return value: {v} void
target: {#?} 0x0 (block)
argument 1: {#"NSMutableAttributedString"} 0x0
Exception: value for key '<no key>' was of unexpected class 'NSMutableAttributedString'. Allowed classes are '{(
(
NSMutableAttributedString,
NSAttributedString,
NSColor,
NSFont,
NSString
)
)}'.
Anybody has transferred NSAttributtedText via XPC Service succesfully?
EDIT: I got a reply to my message on devforums, a workaround is to use an NSSet and to cast it as Set when passing to to setClasses(). Another issue is that there already are pre-set classes for all selectors, and therefore you need to add your own to the current ones, rather than set yours only. Here's a working code :
let interface = NSXPCInterface(withProtocol: MyProtocol.self)
let expectedClasses = NSSet.setWithArray([[NSMutableAttributedString.self, NSAttributedString.self, NSColor.self, NSFont.self])
let currentExpectedClasses = interface.classesForSelector("attributtedText:withReply:", argumentIndex: 0, ofReply: false) as NSSet
let allClasses = currentExpectedClasses.setByAddingSet(expectedClasses)
interface.setClasses(allClasses as Set<NSObject>, forSelector: "attributtedText:withReply:", argumentIndex: 0, ofReply: false)
Original answer :
This will only be a partial answer as I haven't found the right way to do this either yet, but
let incommingClasses:Set = Set(arrayLiteral: [NSMutableAttributedString.self, NSAttributedString.self, NSColor.self, NSFont.self, NSString.self, ])
returns a Set<NSArray>, which is not what you want. I assume you added the 'arrayLiteral' argument label because the compiler told you so, however this compiles :
let foo = Set(["string1", "string2"])
and it returns a Set<String>.
The problem is that I couldn't find a way to create a Set of class types. I've asked on Apple's devforums : https://devforums.apple.com/thread/271316 but unless I'm missing something obvious, this looks like an API bug.

JMeter BeanShell Assertion encounted "\\" after ""

My BeanShell Assertion returns the following result as error:
Assertion error: true
Assertion failure: false
Assertion failure message: org.apache.jorphan.util.JMeterException: Error invoking bsh method: eval
Sourced file: inline evaluation of: `` String sentText = \"Changed the TEXT\"; String receivedText = \"Changed the TEXT\"; . . . '' Token Parsing Error: Lexical error at line 2, column 18. Encountered: "\\" (92), after : ""
I have used a BeanShell PreProcessor to set a property as following and I use it in an edit, which works fine.
${__setProperty(textEdit,\"Changed the TEXT\")}
Then I get the information using a GET call and I use the following regular expression to get that specific information back.
\"edittedText\":(\".*?\")}
Then I use BeanShell Assertion to put the result from that regular expression in the property textEditPost like this. In that BeanShell Assertion I also check if the changed value is the new value.
${__setProperty(textEditPost,${textEditPost})}
String sentText = ${__property(textEdit)};
String receivedText = ${__property(textEditPost)};
if (sentText.equals(receivedText))
{
Failure = false;
}
else
{
Failure = true;
FailureMessage = "The Text does not match, expected: " + sentText + " but found: " + receivedText;
}
I have absolutely no idea where the error on encountering the two backslashes is coming from, as both Strings contain the same data.
Does anyone have an idea why this is happening and a possible solution?
I have found the problem after making some BeanShell Assertions for other things. And I also feel pretty stupid now for not realizing this earlier...
The problem is that the value in the property textEdit is \"Changed the TEXT\" and thus starts with a backslash. Due to this backslash the program has no idea what to do with it when trying to assign it to the String variable sentText or when using the property directly in the if statement.
By placing the property call between quotes the program can properly save it in the String variable. Like this:
${__setProperty(textEditPost,${textEditPost})}
String sentText = "${__property(textEdit)}";
String receivedText = "${__property(textEditPost)}";
if (sentText.equals(receivedText))
{
Failure = false;
}
else
{
Failure = true;
FailureMessage = "The Text does not match, expected: " + sentText + " but found: " + receivedText;
}
I hope this can help others with similar problems too.

SecSignVerifyTransform crashing in Swift with CSSM error Code=-2147415790

I'm trying to obtain a digital signature for a XML string using a RSA private key using Swift as command-line script (to be called from FileMaker later).
The compiler kept crashing with "segmentation fault 11" and then "Illegal Instruction: 4" and I kept drilling down until I (think) I found the problem, but it's completely beyond me, so please, please help!! ;) :)
As the title says, when I invoke SecTransformExecute on my SecSignTransform, with a binary version of my String as input attribute, I get the following error message:
Error Domain=Internal CSSM error Code=-2147415790 "The operation
couldn’t be completed. (Internal CSSM error error -2147415790 -
Internal error #80010912 at __SignTransform_block_invoke_2
/SourceCache/Security/Security-57031.1.35/Security/libsecurity_transform/lib/SecSignVerifyTransform.c:279)" UserInfo=0x7fc620e23aa0 {NSDescription=Internal error #80010912 at
__SignTransform_block_invoke_2 /SourceCache/Security/Security-57031.1.35/Security/libsecurity_transform/lib/SecSignVerifyTransform.c:279,
Originating Transform=CoreFoundationObject}
Here is the relevant part of my code:
import Foundation
import CoreFoundation
import Security
var signer: SecTransformRef
var signedData, digestData: NSData
var error: Unmanaged<CFErrorRef>?
var status: OSStatus
var key: SecKey
var anyItem: Unmanaged<AnyObject>?
var keySearchDict: [String : AnyObject]
let keyMatch = "[*place search tag here*]" as String
// turns a string into a binary to sign
let str = "Hello World"
let uintData = [UInt8](str.utf8)
let sourceData = CFDataCreate(kCFAllocatorDefault, uintData, countElements(uintData))
// sets up keySearchDict to query Keychain
keySearchDict = [(kSecClass as String): (kSecClassKey as String), (kSecMatchSubjectContains as String): keyMatch, (kSecReturnRef as String): kCFBooleanTrue]
// gets private key using keySearchDict
status = SecItemCopyMatching(keySearchDict, &anyItem)
key = (anyItem!.takeRetainedValue() as SecKey)
if status != 0 { println("status is: \(SecCopyErrorMessageString(status, &error).takeRetainedValue())") }
// creates SecTransform object using key
signer = SecSignTransformCreate(key, &error).takeRetainedValue()
if error == nil { println("signer transform creation error == nil") } else { println(error) }
// signer to get data from sourceData
SecTransformSetAttribute(signer, kSecTransformInputAttributeName, sourceData!, &error)
if error == nil { println("signer attribute setting error == nil") } else { println(error) }
// execute the transform
//signedData = (SecTransformExecute(signer, &error) as NSData)
let anything = SecTransformExecute(signer, &error)
if error == nil { println("signer execute error == nil") } else { println("erro: \(error!.takeRetainedValue())"); println(CFErrorGetCode(error!.takeRetainedValue())) }
println("anything = \(anything)")
//println(signedData)
I'm not very familiar with objc and actually not quite a proper coder, so please forgive my poor coding style ;) Also, sorry if I'm posting too much of it, but I figured better more than less...
Maybe I'm doing something wrong when transforming the String to binary for signing? I tried it both using CFData and NSData (to make this self contained, I'm using "Hello World" as my String, but in my code I actually load a UTF8 encoded XML from a file using NSData(contentsOfFile:) yet both generate the same error...)
Thanks you so much for your help! It's being a great learning experience, but I've been at it for over a week full-time now, so I really can use a break!! ;) :D
I have found a solution. The code no longer crashes, and I connected to the web service successfully after it, and the XMLDSIG signature was accepted by it (see related Question on XMLDSIG if interested in details on canonicalization and xml reference).
The key I was using is not compatible with signing (not sure why or even what the key was, actually...)
I was looking into counter-authenticating with a server using a X509 certificate (for an unrelated part of my solution) when I came across the SecIdentity class, needed to create a SecCredential together with the certificate and authenticate with the server.
I saw Identities embed a private key, and thought if could work for me. And it did!
Here are the changes I made:
Changed the kSecClass to kSecClassIdentity in the search dictionary
Retrieved the SecIdentity using SecItemCopyMatching
After casting it accordingly, used SecIdentityCopyPrivateKey to retrieve the private key into a SecKeyRef
Used this key in SecSignTransform, and voilà!! It worked!
Here is the working code:
// ...
// get the SecIdentity (substitutes KeySearchDict etc)
idSearchDict = [(kSecClass as String): (kSecClassIdentity as String), (kSecMatchSubjectContains as String): keyMatch, (kSecReturnRef as String):
status = SecItemCopyMatching(idSearchDict, &anyItem)
id = (anyItem!.takeRetainedValue() as SecIdentity)
// Retrieve the private key from SecIdentity
var KeyRef: Unmanaged<SecKeyRef>?
SecIdentityCopyPrivateKey(id, &KeyRef)
priKey = (KeyRef!.takeRetainedValue() as SecKey)
// Create SecSign using the private key
signer = SecSignTransformCreate(priKey, &error).takeRetainedValue()
if error != nil { print("signer transform creation error: ") ; println(error) }
/ signer to get data from sourceData
// ...
I'll post another question with the difficulties I'm facing with XMLDSIG, and add it to the comments, in case anyone is interested. I've already solved that too, and the answer is there in case you need it.
Thanks to everyone who tried to help, and hope this saves someone a lot of time and headache in the future!!
PS: loving Swift, otherwise 😉 😃

Resources