1

I am working within Xcode and have an iOS application that you input information and the app connects to a DB via a PHP file. There is no problem when uploading, a name or an email address. But for some reason when it comes to uploading a good amount of text, via a UITextView, there becomes a problem. It succeeds when there are no punctuation at all. But when there is a period, or a question mark, it does not get uploaded to the server, it just fails. But with the email field, there is no problem when it comes to periods or even that @ symbol. I am not fluent in PHP or MySQL backend stuff, so I am very confused. Here is the code for the php file:

if (isset ($_GET["firstName"]) && isset($_GET["lastName"]) && isset($_GET["emailAddress"]) && isset($_GET["deviceType"]) && isset($_GET["problemTextField"]) && isset($_GET["iosVersion"])){
    $firstName = $_GET["firstName"];
    $lastName = $_GET["lastName"];
    $emailAddress = $_GET["emailAddress"];
    $deviceType = $_GET["deviceType"];
    $problemTextField = $_GET["problemTextField"];
    $iosVersion = $_GET["iosVersion"];

} else {
    $firstName = "User first name";
    $lastName = "User last name";
    $emailAddress = "User email address";
    $deviceType = "User device type";
    $problemTextField = "User problem text field";
    $iosVersion = "User ios version";
}

$con = mysql_connect($DB_HostName,$DB_User,$DB_Pass) or die(mysql_error()); 
mysql_select_db($DB_Name,$con) or die(mysql_error()); 

$sql = "insert into $DB_Table (firstName, lastName, emailAddress, deviceType, problemTextField, iosVersion, Status, Second_Status) values('$firstName','$lastName',
    '$emailAddress','$deviceType','$problemTextField','$iosVersion', 'Unanswered', 'Answered')";
  $res = mysql_query($sql,$con) or die(mysql_error());

mysql_close($con);
if ($res) {
  echo "success";
}else{
  echo "failed";
}

Like I said, I am not fluent in PHP, so please be nice when pulling apart my syntax for the PHP file.

EDIT: After a whole day of debugging, I have realized that if I take away spaces from in between words, everything is fine. Is there a reason for this? I don't want to have to put plus's in between everything, I know that is not correct.

Here is my Xcode code:

NSString *strURL = [NSString stringWithFormat:@"http://www.website.com/phpFile.php?firstName=%@&lastName=%@&emailAddress=%@&deviceType=%@&problemTextField=%@&iosVersion=%@", firstName.text, lastName.text, emailAddress.text, deviceType.text, self.problemTextBox.text, iosVersion.text];

    // to execute php code
    NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:strURL]];

    // to receive the returend value
    NSString *strResult = [[NSString alloc] initWithData:dataURL encoding:NSUTF8StringEncoding];`
  • Try echo your $sql just before mysql_query – Jompper Nov 25 '13 at 13:26
  • What field is it? What type of field is in the database? What encoding does your table has? – Leonardo Nov 25 '13 at 13:26
  • Not an answer but a recommendation: Don't use the mysql_* functions, they are deprecated and will be gone soon. Check out Mysqli_* or PDO, both are mentioned in the php.net mysql_* deprecated message! :) – Jite Nov 25 '13 at 13:29
  • Also try echo mysql_error($con); after mysql_query to see error message – Jompper Nov 25 '13 at 13:29
  • 1
    Using mysqli or pdo with prepared statements would likely fix the problem too! – Jite Nov 25 '13 at 13:29
  • @Leonardo In Xcode? If so, they are all UITextField's except for the UITextView. In the DB they are all varchar fields and I am pretty sure the encoding I set in Xcode is NSUTF8Encoding, if thats what you're referring to. –  Nov 25 '13 at 13:29
  • @Jite thank you for being so nice! Like I said, I don't know php as well as I know objective-c. So would you be bale to elaborate a little more? Or maybe link me to the correct source for the information how to do that. Thanks :) –  Nov 25 '13 at 13:31
  • +1 for PDO / MySQLi. Your code is very dangerous, you should at least escape user input. – Jompper Nov 25 '13 at 13:32
  • http://us2.php.net/manual/en/book.mysqli.php <- Mysqli documentations, I recommend mysqli due to it being quite close to the Mysql_* functions in some of the usages, but most people would likely recommend PDO cause of it not being as bound to the database type. The main function you might want to look at is http://us2.php.net/manual/en/mysqli.prepare.php Prepared statements makes database code a whole lot safer, but please, read about it on php.net! – Jite Nov 25 '13 at 13:34
  • @Rob - go for it if you think it's appropriate. – rmaddy Nov 25 '13 at 16:24

4 Answers4

1

First of, do not use the mysql_* functions, they are deprecated and will be removed from php soon. Check out mysqli or PDO for a replacement.

When talking to a database, its important that the input is checked so its not bad.
You can do this with escape functions or prefferably prepared statements.
Both mysqli and pdo have prepared statements.
The prepared statements will help you with escaping, as you let the mysql wrapper know what type of data it should expect, giving it anything else will cause an error.

Your code is very open for something called SQL Injections (http://en.wikipedia.org/wiki/SQL_injection) and thats a bad thing.
This is probably why your query breaks at certain characters.
Prepared statements helps to prevent this!

Please read the mysqli documentation and specifically mysqli prepared statements:
http://php.net/manual/en/book.mysqli.php
http://php.net/manual/en/mysqli.prepare.php

I recommend Mysqli due to the fact that its more similar to the mysql api than PDO is.
But PDO might be better if you don't mind learning something new!

Also, as ddelnado mentions, GET might not be optimal for this, POST might be better suited.

Jite
  • 5,761
  • 2
  • 23
  • 37
  • 1
    I will look into implementing these changes within my code. Thank you for taking your time help out! –  Nov 25 '13 at 13:50
0

use mysql_real_escape_string like

 $firstName = mysql_real_escape_string($_GET["firstName"]);

before all get values

Thanks

user7789076
  • 798
  • 2
  • 12
  • 25
0

You should not be using the $_GET superglobal. The Get method has a limit on the size of the data where as the $_POST superglobal has not limit. So your code should look like this.\

if (isset ($_POST["firstName"]) && isset($_POST["lastName"]) && isset($_POST["emailAddress"]) && isset($_POST["deviceType"]) && isset($_POST["problemTextField"]) && isset($_POST["iosVersion"])){
$firstName = $_POST["firstName"];
$lastName = $_POST["lastName"];
$emailAddress = $_POST["emailAddress"];
$deviceType = $_POST["deviceType"];
$problemTextField = $_POST["problemTextField"];
$iosVersion = $_POST["iosVersion"];

I don't know what form you are using to submit this but the method of that form needs to be post also. In addition you should always escape your variables before inserting them in a database so sql injection does not occur.

ddelnano
  • 459
  • 5
  • 19
0

A couple of observations:

  1. You said:

But when there is a period, or a question mark, it does not get uploaded to the server, it just fails.

Your question presumes that the problem rests in the PHP code, but it sounds like you might not properly be percent escaping the parameters when creating the request. Notably, many people erroneously use stringByAddingPercentEscapesUsingEncoding (which will percent escape some characters, but not others). Notably, there are "legal" characters that are valid in a URL, but are not valid within a POST/GET parameter, so you need to specify those "legal" characters that should also be percent escaped (e.g. ?, &, +, etc.) within a parameter.

In short, you really want to use CFURLCreateStringByAddingPercentEscapes, which allows you to specify additional characters that should be escaped per RFC 3986. For example, I've used the following NSString category.

    @implementation NSString (URLEncode)
    
    - (NSString *)stringForHTTPRequest
    {
        return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                                         (CFStringRef)self,
                                                                         NULL,
                                                                         (CFStringRef)@":/?@!$&'()*+,;=",
                                                                         kCFStringEncodingUTF8));
    }
    
    @end

Or use a framework like AFNetworking which simplifies the process of creating requests and takes care of this for you.

  1. Note, this PHP code is returning simple string response. Instead, I'd suggest creating JSON response, which will make it easier for the Objective-C code to handle and interpret the response (and report/log the error). For example, if using the procedural rendition of mysqli:

     <?php
    
     // specify that this will return JSON
    
     header('Content-type: application/json');
    
     // open database
    
     $con = mysqli_connect("localhost","user","password","database");
    
     // Check connection
    
     if (mysqli_connect_errno())
     {
         echo json_encode(array("success" => false, "message" => mysqli_connect_error(), "sqlerrno" => mysqli_connect_errno()));
         exit;
     }
    
     // get the parameters
    
     $field1 = mysqli_real_escape_string($con, $_REQUEST["field1"]);
     $field2 = mysqli_real_escape_string($con, $_REQUEST["field2"]);
    
     // perform the insert
    
     $sql = "INSERT INTO sometable (field1, field2) VALUES ('{$field1}', '{$field2}')";
    
     if (!mysqli_query($con, $sql))
     {
         $response = array("success" => false, "message" => mysqli_error($con), "sqlerrno" => mysqli_errno($con), "sqlstate" => mysqli_sqlstate($con));
     }
     else
     {
         $response = array("success" => true);
     }
    
     echo json_encode($response);
    
     mysqli_close($con);
    
     ?>
    

Or, if using the object-oriented style:

    <?php
    
    header('Content-type: application/json');
    
    $mysqli = new mysqli("localhost", "user", "password", "database");
    
    // check connection 
    
    if ($mysqli->connect_errno) {
        echo json_encode(array("success" => false, "message" => $mysqli->connect_error, "sqlerrno" => $mysqli->connect_errno));
        exit();
    }
    
    // perform the insert
    
    $sql = "INSERT INTO sometable (field1, field2) VALUES (?, ?)";
    
    if ($stmt = $mysqli->prepare($sql)) {
        $stmt->bind_param("ss", $_REQUEST["field1"], $_REQUEST["field2"]);
        
        if (!$stmt->execute())
            $response = array("success" => false, "message" => $mysqli->error, "sqlerrno" => $mysqli->errno, "sqlstate" => $mysqli->sqlstate);
        else
            $response = array("success" => true);
    
        $stmt->close();
    } else {
        $response = array("success" => false, "message" => $mysqli->error, "sqlerrno" => $mysqli->errno, "sqlstate" => $mysqli->sqlstate);
    }
    
    $mysqli->close();
    
    echo json_encode($response);
    
    ?>

This way, the Objective-C app can receive the response, parse the JSON, and look at success to determine whether the operation was successful or not, and look at message for the error message if it wasn't successful. This just permits a more robust conversation between app and server.

  1. By the way, I'd suggest that you use mysqli_real_escape_string or manually bind parameters to a prepared statement to protect against SQL injection attacks or unintended errors arising from unescaped strings in your SQL.

  2. I'd also suggest you create a POST request rather than a GET request which allows larger values.

Community
  • 1
  • 1
Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • I am currently away from my computer, so I cannot get my exact code from Xcode. But what I am doing is upon a button press to 'submit' the info into the DB, I get the php file through a URLstring, then execute with an nsdata statement, and then get the data statement to say success or not. Would that not be the right way to do it? Or should I add your code to my method? As soon as I get home I will edit this with my code. –  Nov 25 '13 at 15:38
  • As well as my previous statement. I am really going to dive into the AFNetworking framework, which will probably make this easier and give me more powerful program. –  Nov 25 '13 at 15:45
  • @user1813278 You should probably create a `POST` request, which doesn't just add the parameters to the URL (like you can do with a `GET` request), but rather adds the `POST` parameters to the body of the request. You can do it yourself if you want, but entails creating a `NSMutableURLRequest`, using `setHTTPMethod` to `POST`, using `setHTTPBody` with the `POST` variables, setting a few other header values, etc. AFNetworking does all of that for you (as well as properly percent escaping the values and doing the parsing of the JSON response), so it's a little easier. Good luck! – Rob Nov 25 '13 at 15:50
  • here is my Xcode code `NSString *strURL = [NSString stringWithFormat:@"http://www.website.com/phpFile.php?firstName=%@&lastName=%@&emailAddress=%@&deviceType=%@&problemTextField=%@&iosVersion=%@", firstName.text, lastName.text, emailAddress.text, deviceType.text, self.problemTextBox.text, iosVersion.text]; // to execute php code NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:strURL]]; // to receive the returend value NSString *strResult = [[NSString alloc] initWithData:dataURL encoding:NSUTF8StringEncoding];` –  Nov 25 '13 at 20:26
  • as well as that, I have noticed, after a whole day of debugging, that if I take the spaces away from the text, everything is fine. As an example, I know this is frowned upon, but if you put a plus in every spot as a space, there is no errors. Is there a reason for this? –  Nov 25 '13 at 20:28
  • I am sorry. I am just a little confused with this. For some reason, my mind can't grasp what I am doing. I implemented that `stringForHTTPRequest` in my code, but what do I do with that and the textfields? –  Nov 26 '13 at 01:59
  • @user1813278 We should move this to chat: http://chat.stackoverflow.com/rooms/41918/problems-with-php-and-mysql – Rob Nov 26 '13 at 02:56