I'm passing a large set of strings to my server from iOS (Swift) to a PHP file via POST. Unfortunately, if a user places an ampersand (&) in a field, the rest of the field is lost. I understand why (& signifies the next field in the message) but I'm not sure how to fix.
func UploadToSql(plan: LessonPlan, isNew: Bool, callBack: ((data: NSData!, response: NSURLResponse!, error: NSError!) -> Void)?) {
let url = NSURL(string: "https://myserver.com/receive.php")!
var request:NSMutableURLRequest = NSMutableURLRequest(URL:url)
var bodyData = "Author=\(plan.author)&title=\(plan.title)&grade=\(plan.grade)&date=\"\(plan.date)\"&element1=\(plan.element1)&objective1=\(convertedFields[0])&element2=\(plan.element2)&objective2=\(convertedFields[1])&element3=\(plan.element3)&objective3=\(convertedFields[2])&coreProcess1=\(plan.coreProcess1)&coreStrand1=\(plan.coreStrand1)&coreStandard1=\(plan.coreStandard1)&coreProcess2=\(plan.coreProcess2)&coreStrand2=\(plan.coreStrand2)&coreStandard2=\(plan.coreStandard2)&coreProcess3=\(plan.coreProcess3)&coreStrand3=\(plan.coreStrand3)&coreStandard3=\(plan.coreStandard3)&media1=\(plan.media1)&media2=\(plan.media2)&media3=\(plan.media3)&media4=\(plan.media4)&media5=\(plan.media5)&media6=\(plan.media6)&repertoire1=\(convertedFields[3])&repertoire2=\(convertedFields[4])&repertoire3=\(convertedFields[5])&process=\(convertedFields[6])&assessment=\(convertedFields[7])&stateCat1=\(plan.stateCat1)&stateCat2=\(plan.stateCat2)&stateCat3=\(plan.stateCat3)&stateStand1=\(plan.stateStand1)&stateStand2=\(plan.stateStand2)&stateStand3=\(plan.stateStand3)&comment=\(plan.comment)&shared=\(sharedInt!)&authorName=\(plan.authorName)" + planID
request.HTTPMethod = "POST"
request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil {
println("error=\(error)")
return
}
println("response = \(response)")
callBack?(data: data, response: response, error: error)
return
}
task.resume()
}
Typically for a webrequest like that it uses % followed by the ascii hex value. The hex value for & is 26, so it would be %26
google.com/#q=red%26white is example of a google search for red&white, which uses that replacement
Its called URL encoding or percent encoding and here is another question with an answer on how to do more broad URL encoding: stackoverflow.com/questions/24551816/swift-encode-url
Note that you would have to URL encode each element you were interpolating into the string, not the whole result string, as you want to keep your &'s that separate parameters.
This one is working for me. I am also using PHP/MySQL with NSURLSession.
func stringByAddingPercentEncodingForFormData(plusForSpace: Bool=false) -> String? {
let unreserved = "*-._"
let allowed = NSMutableCharacterSet.alphanumericCharacterSet()
allowed.addCharactersInString(unreserved)
if plusForSpace {
allowed.addCharactersInString(" ")
}
var encoded = stringByAddingPercentEncodingWithAllowedCharacters(allowed)
if plusForSpace {
encoded = encoded?.stringByReplacingOccurrencesOfString(" ",
withString: "+")
}
return encoded
}
Found above function from this link: http://useyourloaf.com/blog/how-to-percent-encode-a-url-string/.
Related
I want to run the same line of code but incrementing the number "prodottiNome_prodotto0" and forKey: ("nome_prodotto0") always.
let prodotti = jsonData.value(forKey: "prodotti") as! NSDictionary
let prodottiNome_prodotto0 = prodotti.value(forKey: "nome_prodotto0") as! String
self.defaultValues.set(prodottiNome_prodotto0, forKey: "nome_prodotto0")
nome_prodotto0 refers to the result of a return in php ------------>
"prodotti":{"nome_prodotto0":"farina","nome_prodotto1":"dfd"}
If I understand what you're asking, your code might look like this:
let max = 50 //Or whatever limit you want to use
for i in 0...max {
let key = "nome_prodotto" + String(i)
//Use `if let` so you don't crash if a value is not a string
//Don't use `value(forKey:)` on a dictionary. That's a KVO method
if let value = prodotti[key] as? String {
self.defaultValues.set(value, forKey: key)
{
}
I'm trying to send data from a VB.NET Application to a php application, i found this code:
Private Function SendRequest(uri As Uri, jsonDataBytes As Byte(),contentType As String, method As String) As String
Dim req As WebRequest = WebRequest.Create(uri)
req.ContentType = contentType
req.Method = method
req.ContentLength = jsonDataBytes.Length
Dim stream = req.GetRequestStream()
stream.Write(jsonDataBytes, 0, jsonDataBytes.Length)
stream.Close()
Dim response = req.GetResponse().GetResponseStream()
Dim reader As New StreamReader(response)
Dim res = reader.ReadToEnd()
reader.Close()
response.Close()
Return res
End Function
Dim data = Encoding.UTF8.GetBytes(jsonSring)
Dim result_post = SendRequest(uri, data, "application/json", "POST")
at: source
But I can't get the posted data on php. It sends the headers, but the data no.
So, I need help to figure it out what is missing.
I also had same issue and got solution from comments only. As you are passing binary data then in php you need to read binary data as raw input
To get the Raw Post Data:
<?php $postdata = file_get_contents("php://input"); ?>
I am in the process of making an app that retrieves data from a mysql database.
I have gotten this to work as it displayed my information where I wanted.
I wake up the next day and my website is down so i make another one but my code stopped working and gives me this error:
Data downloaded
Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.}
i know the error happens on the func parseJSON becuase i took off the "self.parseJSON" and it downloaded the data without displaying the error but it still doesnt display.
here is the code where the error is happening:
func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
if error != nil {
print("Failed to download data")
}else {
print("Data downloaded")
self.parseJSON()
}
}
func parseJSON() {
var jsonResult: NSMutableArray = NSMutableArray()
do{
jsonResult = try NSJSONSerialization.JSONObjectWithData(self.data, options:NSJSONReadingOptions.AllowFragments) as! NSMutableArray
} catch let error as NSError {
print(error)
}
var jsonElement: NSDictionary = NSDictionary()
let pools: NSMutableArray = NSMutableArray()
for(var i = 0; i < jsonResult.count; i++)
{
jsonElement = jsonResult[i] as! NSDictionary
let pool = PoolModel()
//the following insures none of the JsonElement values are nil through optional binding
if let Date = jsonElement["Date"] as? String,
let PH = jsonElement["PH"] as? String,
let CH = jsonElement["CH"] as? String,
let Alk = jsonElement["Alk"] as? String,
let CYA = jsonElement["CYA"] as? String,
let TEMP = jsonElement["TEMP"] as? String
{
pool.Date = Date
pool.PH = PH
pool.CH = CH
pool.Alk = Alk
pool.CYA = CYA
pool.TEMP = TEMP
}
pools.addObject(pool)
}
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.delegate.itemsDownloaded(pools)
})
}
}
Did I delete something from my code or could it be the php file where I getting the data?
Data downloaded
JSON:
<3c68746d 6c3e3c62 6f64793e 3c736372 69707420 74797065 3d227465 78742f6a
61766173 63726970 74222073 72633d22 2f616573 2e6a7322 203e3c2f 73637269 70743e3c 73637269 70743e66 756e6374 696f6e20 746f4e75 6d626572 73286429
7b766172 20653d5b 5d3b642e 7265706c 61636528 2f282e2e 292f672c 66756e63 74696f6e
2864297b 652e7075 73682870 61727365 496e7428 642c3136 29297d29 3b726574 75726e20 657d6675 6e637469 6f6e2074 6f486578 28297b66 6f722876 61722064 3d5b5d2c 643d313d 3d617267 756d656e 74732e6c 656e6774 68262661 7267756d 656e7473 5b305d2e 636f6e73 74727563 746f723d 3d417272 61793f61 7267756d 656e7473 5b305d3a 61726775 6d656e74 732c653d 22222c66 3d303b66 3c642e6c 656e6774 683b662b 2b29652b 3d283136 3e645b66 5d3f2230 223a2222 292b645b 665d2e74 6f537472 696e6728 3136293b 72657475 726e2065 2e746f4c 6f776572 43617365 28297d76 61722061 3d746f4e 756d6265 72732822 66363535 62613964 30396131 31326434 39363863 36333537 39646235 39306234 22292c62 3d746f4e 756d6265 72732822 39383334 34633265 65653836 63333939 34383930 35393235 38356234 39663830 22292c63 3d746f4e 756d6265 72732822 34333331 39653035 63313431 63366231 64356165 62343931 33636238 66356232 22293b64 6f63756d 656e742e 636f6f6b 69653d22 5f5f7465 73743d22 2b746f48 65782873 6c6f7741 45532e64 65637279 70742863 2c322c61 2c622929 2b223b20 65787069 7265733d 5468752c 2033312d 4465632d 33372032 333a3535 3a353520 474d543b 20706174 683d2f22 3b20646f 63756d65 6e742e63 6f6f6b69 653d2272 65666572 7265723d 222b6573 63617065 28646f63 756d656e 742e7265 66657272 6572293b 206c6f63 6174696f 6e2e6872 65663d22 68747470 3a2f2f70 6f6f6c63 616c632e 62796574 686f7374 31312e63 6f6d2f73 65727669 63652e70 68703f63 6b617474 656d7074 3d31223b 3c2f7363 72697074 3e3c6e6f 73637269 70743e54 68697320 73697465 20726571 75697265 73204a61 76617363 72697074 20746f20 776f726b 2c20706c 65617365 20656e61 626c6520 4a617661 73637269 70742069 6e20796f 75722062 726f7773 6572206f 72207573 65206120 62726f77 73657220 77697468 204a6176 61736372 69707420 73757070 6f72743c 2f6e6f73 63726970 743e3c2f 626f6479 3e3c2f68 746d6c3e>
Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.}
Also the php file is working fine on the website as it displays the info online
here is a link to that file
poolcalc php
Update answer for updated question:
The JSON hex data is the following string decoded as UTF-8:
<tmll<booy><<criit ttpe==texx/jaaascciptt srr="//es..s" </ssripp><ssripp>fuuctiin ttNummerssd){{ar =[]]d.rrplaae(//..))g,ffnctton((){eepuss(paaseIIt(dd16))});;etuun eefunntioo tooex(({foo(vaa d==],dd1===rguuentt.leegthh&arrumeets[[].ccnsttucttr===rraa?arrumeets[[]:aagummntsse="",f==;f<<.leegthhf+++e+==16>>[f]]"0""""))d[ff.tootriig(11);rrturr e..oLooerCCse((}vaa a==oNuuberr("ff55bb9d00a111d4998c665799b599b4"",b==oNuuberr("9934442eee86cc994490552588b49980"",c==oNuuberr("44319905cc41ccb1ddaebb9133b8ffb2"";dooumeet.ccokii="__tess="++oHee(sllwAEE.deerypp(c,,,a,,))++; eepirrs=TTu, 1-DDc-33 23355::5 GGT; athh/";;doccmenn.cookiee"reeerrrr=""esccpe((ocuuenttreffrree); ocaaionnhree="hhtp::/poolcaac.bbethhst11.coo/seevicc.phh?ckktteept==";<<scrrpt>>nossripp>Thhs sste equuressJavvscrrpt o wwrk,,pleese nabbe JJvassripp innyouu brrwsee orruseea bbowssr wwth avaacriit ssppoot<//oscciptt</bbdy>>/httl>
That is mangled html not JSON.
For whatever reason that I am still trying to figure out, I at least know the source. I thought it was the code in my xcode project. Using PostMan on chrome, I put in the link http://poolcalc.byethost11.com/service.php and it sends pack this:
<html>
<body>
<script type="text/javascript" src="/aes.js" ></script>
<script>function toNumbers(d){var e=[];d.replace(/(..)/g,function(d){e.push(parseInt(d,16))});return e}function toHex(){for(var d=[],d=1==arguments.length&&arguments[0].constructor==Array?arguments[0]:arguments,e="",f=0;f
<d.length;f++)e+=(16>d[f]?"0":"")+d[f].toString(16);return e.toLowerCase()}var a=toNumbers("f655ba9d09a112d4968c63579db590b4"),b=toNumbers("98344c2eee86c3994890592585b49f80"),c=toNumbers("43319e05c141c6b1d5aeb4913cb8f5b2");document.cookie="__test="+toHex(slowAES.decrypt(c,2,a,b))+"; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/"; document.cookie="referrer="+escape(document.referrer); location.href="http://poolcalc.byethost11.com/service.php?ckattempt=2";
</script>
<noscript>This site requires Javascript to work, please enable Javascript in your browser or use a browser with Javascript support</noscript>
</body>
</html>
I dont understand why its doing that but that would be why the program doesnt like it.
I want to crypt privateKey & publicKey to sha1 in base64 with Swift, but the output is not the one I see in PHP urlencode base64_encode which I tried in Codecademy:"https://www.codecademy.com/courses/web-beginner-en-StaFQ/0/3?curriculum_id=5124ef4c78d510dd89003eb8".
Pls see the following codes in Swift and Codecademy:
Swift:
//pls see func dataFromHexadecimalString() details here "http://stackoverflow.com/questions/26501276/convert-string-to-hex-string-in-swift/26502285#26502285"
extension String {
func dataFromHexadecimalString() -> NSData? {
let trimmedString = self.stringByTrimmingCharactersInSet(NSCharacterSet(charactersInString: "<> ")).stringByReplacingOccurrencesOfString(" ", withString: "")
var error: NSError?
let regex = NSRegularExpression(pattern: "^[0-9a-f]*$", options: .CaseInsensitive, error: &error)
let found = regex?.firstMatchInString(trimmedString, options: nil, range: NSMakeRange(0, count(trimmedString)))
if found == nil || found?.range.location == NSNotFound || count(trimmedString) % 2 != 0 {
return nil
}
let data = NSMutableData(capacity: count(trimmedString) / 2)
for var index = trimmedString.startIndex; index < trimmedString.endIndex; index = index.successor().successor() {
let byteString = trimmedString.substringWithRange(Range<String.Index>(start: index, end: index.successor().successor()))
let num = UInt8(byteString.withCString { strtoul($0, nil, 16) })
data?.appendBytes([num] as [UInt8], length: 1)
}
return data
}
}
func URLEcodekey() -> String {
let appid="a1b2c34d5e"
let privateKey="ef7d6s0d"
let areaid="101020900"
let time="201507191254"
let publicKey="http://open.weather.com.cn/data/?areaid=\(areaid)&type=forecast_v&date=\(time)&appid=\(appid)"
let cPrivateKey=privateKey.dataUsingEncoding(NSUTF8StringEncoding)!
let cPublicKey=publicKey.dataUsingEncoding(NSUTF8StringEncoding)!
var cHMAC = [CUnsignedChar](count: Int(CC_SHA1_DIGEST_LENGTH), repeatedValue: 0)
CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA1), cPublicKey.bytes, Int(cPublicKey.length), cPrivateKey.bytes, Int(cPrivateKey.length), &cHMAC)
let hexKeyString=NSMutableString(capacity: Int(CC_SHA1_DIGEST_LENGTH))
for byte in cHMAC{
hexKeyString.appendFormat("%02hhx", byte)
}
println("hexKeyString:\(encryptedKey)")
let binaryData = hexKeyString.dataFromHexadecimalString()
let base64String = binaryData?.base64EncodedStringWithOptions(nil)
println("base64String:\(base64String)")
var urlEncodeKey=base64String!.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())!
println("urlEncodeKey:\(urlEncodeKey)")
return urlEncodeMessage
}
the outputs are:
hexKeyString:d4433d42b1505c00a4aa80205171d0d04754d254
base64String:1EM9QrFQXACkqoAgUXHQ0EdU0lQ=
urlEncodeKey:1EM9QrFQXACkqoAgUXHQ0EdU0lQ=
PHP in Codecademy:
echo urlencode(base64_encode(hash_hmac('sha1', " http://open.weather.com.cn/data/?areaid=101020900&type=forecast_v&date=201507191254&appid=a1b2c34d5e", "ef7d6s0d", TRUE)));
the output is:
A5O59Y%2BFbGjhVwaI9JNB7DkcX%2F4%3D // the output is much like the
example in API, which I think maybe the right one.
So, how can I receive the right urlEncodeKey for my privateKey & publicKey like in PHP?
Thank you very much in advance!
You should read more about cryptography and hashing. In your case, there's no public key, private key, ... SHA stands for Secure hash algorithm and what you're trying to get is Hash based authentication code. Check Wikipedia articles about HMAC, SHA-1, Public key, ... I strongly recommend to read more about it otherwise you can create more damage if you misunderstand it.
Back to your problem. It's in one character:
Swift code - let publicKey="http://open.weather.com.cn...
PHP code - hash_hmac('sha1', " http://open.weather.com.cn...
Do you see where the problem is? In your PHP code, there's one space character just before http. This character is not in your Swift code.
Honestly, I didn't check your whole code, because I don't know why you're trying to convert it from hexadecimal string, etc. Used some parts only and rewrote it from scratch for you. Here's working example:
func URLEncodedKey() -> String? {
let appid = "a1b2c34d5e"
let time = "201507191254"
let areaid = "101020900"
let key = "ef7d6s0d"
let string = " http://open.weather.com.cn/data/?areaid=\(areaid)&type=forecast_v&date=\(time)&appid=\(appid)"
// ^ <- in your PHP example, there's space
guard let keyData = key.dataUsingEncoding(NSUTF8StringEncoding),
stringData = string.dataUsingEncoding(NSUTF8StringEncoding),
outputData = NSMutableData(length: Int(CC_SHA1_DIGEST_LENGTH)) else {
return nil
}
outputData.length = Int(CC_SHA1_DIGEST_LENGTH)
CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA1),
keyData.bytes, keyData.length,
stringData.bytes, stringData.length,
outputData.mutableBytes)
return outputData
.base64EncodedStringWithOptions([])
.stringByAddingPercentEncodingWithAllowedCharacters(.URLQueryAllowedCharacterSet())
}
Return value is:
`Optional("A5O59Y+FbGjhVwaI9JNB7DkcX/4=")`
Which is what you get when you decode your PHP output.
Just replace URLQueryAllowedCharacterSet with any of the following character sets:
class func URLUserAllowedCharacterSet() -> NSCharacterSet
class func URLPasswordAllowedCharacterSet() -> NSCharacterSet
class func URLHostAllowedCharacterSet() -> NSCharacterSet
class func URLPathAllowedCharacterSet() -> NSCharacterSet
class func URLQueryAllowedCharacterSet() -> NSCharacterSet
class func URLFragmentAllowedCharacterSet() -> NSCharacterSet
Depends on your use case. IOW in which part of the URL your would like to use it.
How do I get/extract datas from bracket/object in iOS swift???
I used println(datas) to display in Xcode6 console log:
Optional({"status":"fail","message":"Invalid Username or Password"})
note:
server code: php language.
I want to get this datas from that object or array. I don't know what that is.
I want to specifically display status in a specific label.
I want swift code if possible. Thank you very much!!! :D hehe
You PhP code returns a JSON, its like this:
{
"status":"fail",
"message":"Invalid Username or Password"
}
Its an NSDictionary type data, So receive it in an NSDictionary, lets call it responseData.
Then If you want to get status then write this:
let status = responseData ["status"]! as String
For message :
let message = responseData ["message"]! as String
From your provided code:
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
let status = jsonResult ["status"]! as String
println(status)
let message = jsonResult ["message"]! as String
println(message)
})
Hope this helps.. :)
Try it
var jsonText = //your json text
var data : Dictionary<NSObject, NSObject> =
NSJSONSerialization.JSONObjectWithData(text.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!, options: nil, error: nil)