2

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()
}
Tim
  • 2,089
  • 1
  • 12
  • 21
  • Escape your special characters and then unescape them when you need to display them again – Will M. Jun 10 '15 at 17:07
  • @Will I get that, but how? \& doesn't work in Swift. – Tim Jun 10 '15 at 17:08
  • 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 https://www.google.com/#q=red%26white example of a google search for red&white, which uses that replacement – Will M. Jun 10 '15 at 17:11
  • 1
    Its called URL encoding and here is another question with an answer http://stackoverflow.com/questions/24551816/swift-encode-url 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 – Will M. Jun 10 '15 at 17:13
  • @Will that did it! Please add an answer and I will accept. Thanks. – Tim Jun 10 '15 at 17:15

2 Answers2

1

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.

Community
  • 1
  • 1
Will M.
  • 1,864
  • 17
  • 28
  • This was the solution, and as Will said, I had to encode each element, not the full string. Also, the PHP/MySQL process dealt with the %26 and converted it back to an ampersand automatically, so I didn't have to add a decoding step when re-downloading. – Tim Jun 10 '15 at 17:22
0

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/.

Gaurav Singla
  • 2,271
  • 26
  • 43