1

I'm developing an iOS app using Swift 2. I want the login info (user and password) to be stored in a MySQL database online, which is in a godaddy VPS server. This is the class for registration:

import UIKit

class RegisterPageViewController: UIViewController {

    @IBOutlet weak var userEmailTextField: UITextField!
    @IBOutlet weak var userPasswordTextField: UITextField!
    @IBOutlet weak var repeatPasswordTextField: UITextField!
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func registerButtonTapped(sender: AnyObject) {

        let userEmail = userEmailTextField.text
        let userPassword = userPasswordTextField.text
        let userRepeatPassword = repeatPasswordTextField.text

        //Check for empty fields
        if(userEmail!.isEmpty || userPassword!.isEmpty || userRepeatPassword!.isEmpty) {

            //Display alert message
            displayMyAlertMessage("Todos los campos son requeridos")
            return
        }
        //Check if password match
        if(userPassword != userRepeatPassword) {
            //Display an alert message
            displayMyAlertMessage("Passwords no coinciden")
            return
        }

        //Send user data to server side
        let myURL = NSURL(string: "https://gastonberenstein.com/pruebasmysql/userRegister.php")
        let request = NSMutableURLRequest(URL: myURL!)
    request.HTTPMethod = "POST"

    let postString = "email=\(userEmail)&password=\(userPassword)"
    request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
        data, response, error in

        if error != nil {
            print("error=\(error)")
        }

        do {
            var json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSDictionary

            if let parseJSON = json {
                var resultValue = parseJSON["status"] as! String!
                print("result: \(resultValue)")

                var isUserRegistered:Bool = false
                if(resultValue == "Success") {
                    isUserRegistered = true
                }

                var messageToDisplay:String = parseJSON["message"] as! String
                if(!isUserRegistered) {
                    messageToDisplay = parseJSON["message"] as! String
                }

                dispatch_async(dispatch_get_main_queue(), {

                    //Display alert message with confirmation
                    var myAlert = UIAlertController(title: "Alert", message: messageToDisplay, preferredStyle: UIAlertControllerStyle.Alert)

                    let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default){ action in
                        self.dismissViewControllerAnimated(true, completion: nil)
                    }
                    myAlert.addAction(okAction)
                    self.presentViewController(myAlert, animated: true, completion: nil)
                })
            }
        } catch {
            print(error)
        }
    }
    task.resume()
}

func displayMyAlertMessage(userMessage:String) {
    var myAlert = UIAlertController(title:"Alert", message: userMessage, preferredStyle: UIAlertControllerStyle.Alert)

    let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil)
    myAlert.addAction(okAction)

    self.presentViewController(myAlert, animated: true, completion: nil)
}

}

Conn.php:

<?php
  class Conn {
     public static $dbhost = "166.62.92.31";
     //public static $dbhost = "localhost"
     public static $dbuser = "gastonbe_gaston";
     public static $dbpass = "xxx";
     public static $dbname = "gastonbe_pruebasmysql";
  }
?>

MySQLDao.php:

<?php
class MySQLDao {
    var $dbhost = null;
    var $dbuser = null;
    var $dbpass = null;
    var $conn = null;
    var $dbname = null;
    var $result = null;

    function __construct() {
        $this->dbhost = Conn::$dbhost;
        $this->dbuser = Conn::$dbuser;
        $this->dbpass = Conn::$dbpass;
        $this->dbname = Conn::$dbname;
    }

    public function openConnection() {
        $this->conn = new mysqli($this->dbhost, $this->dbuser, $this->dbpass, $this->dbname);
        if (mysqli_connect_errno())
            echo new Exception("No se pudo establecer la conexion a la base de datos");
    }

    public function getConnection() {
        return $this->conn;
    }

    public function closeConnection() {
        if ($this->conn != null)
            $this->conn->close();
    }

    public function getUserDetails($email) {
        $returnValue = array();
        $sql = "select * from users where user_email='" . $email . "'";
        $result = $this->conn->query($sql);
        if ($result != null && (mysqli_num_rows($result) >= 1)) {
            $row = $result.fetch_array(MYSQLI_ASSOC);
            if (!empty($row)) {
                $returnValue = $row;
            }
        }
        return $returnValue;
    }

    public function getUserDetailsWithPassword($email, $userPassword) {
        $returnValue = array();
        $sql = "select id, user_email from users where user_email='" . $email . "' and user_password='" .$userPassword . "'";
        $result = $this->conn->query($sql);
        if ($result != null && (mysqli_num_rows($result) >=1)) {
            $row = $result->fetch_array(MYSQLI_ASSOC);
            if (!empty($row)) {
                $returnValue = $row;
            }
        }
        return $returnValue;
    }

    public function registerUser($email, $password) {
        $sql = "insert into users set user_email=?, user_password=?";
        $statement = $this->conn->prepare($sql);
        if (!$statement)
            throw new Exception($statement->error);
        $statement->bind_param("ss", $email, $password);
        $returnValue = $statement->execute();
        return $returnValue;
    }
}
?>

registerUser.php:

    <?php
   require("Conn.php");
   require("MySQLDao.php");

   $email = htmlentities($_POST["email"]);
   $password = htmlentities($_POST["password"]);

   $returnValue = array();

   if(empty($email) || empty($password)) {
    $returnValue["status"] = "error";
    $returnValue["message"] = "Falta un campo requerido";
    echo json_encode($returnValue);
    return;
   }

   $dao = new MySQLDao();
   $dao->openConnection();
   $userDetails = $dao->getUserDetails($email);

   if(!empty($userDetails)) {
    $returnValue["status"] = "error";
    $returnValue["message"] = "El usuario ya existe";
    echo json_encode($returnValue);
    return;
   }

   $secure_password = md5($password);

   $result = $dao->registerUser($email,$secure_password);

   if($result) {
    $returnValue["status"] = "Success";
    $returnValue["message"] = "Usuario registrado";
    echo json_encode($returnValue);
    return;
   }

   $dao->closeConnection();

   ?>

When I run/debug the app in Xcode, I enter an username and registration into the corresponding fields and in the line 56 where I put a breakpoint:

let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {...

The console throws this error: 2015-11-19 14:02:16.932 userLoginAndRegistration[17265:6170848] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)

Any help? thanks a lot! If i forgot to add any information please let me know.

  • Sorry, the php file for registration is userRegister.php instead of registerUser.php – Gaston Berenstein Nov 19 '15 at 17:36
  • 1
    You should make sure your server is working correctly before you try to build an app that accesses it. Have you verified your server code works? You could use a curl command like `curl --data "email=name@email.com&password=password" https://gastonberenstein.com/pruebasmysql/userRegister.php` for example. – Matt Long Nov 19 '15 at 18:03
  • Thank you for your answer Matt. I just did that and the answer was this: curl: (60) SSL certificate problem: Invalid certificate chain More details here: http://curl.haxx.se/docs/sslcerts.html – Gaston Berenstein Nov 19 '15 at 18:17
  • and this: curl performs SSL certificate verification by default, using a "bundle" of Certificate Authority (CA) public keys (CA certs). If the default bundle file isn't adequate, you can specify an alternate file using the --cacert option. If this HTTPS server uses a certificate signed by a CA represented in the bundle, the certificate verification probably failed due to a problem with the certificate (it might be expired, or the name might not match the domain name in the URL). If you'd like to turn off curl's verification of the certificate, use the -k (or --insecure) option. – Gaston Berenstein Nov 19 '15 at 18:18
  • I've done the same but with http instead of https, and the answer was:
    Fatal error: Class 'mysqli' not found in /home/gastonberenstein/public_html/pruebasmysql/MySQLDao.php on line 18
    – Gaston Berenstein Nov 19 '15 at 18:25

2 Answers2

0

I had two errors:

  1. The URL of the PHP file should start with 'http' instead of 'https'.
  2. I didn't install MySQLi in the VPS server (found here: Fatal error: Class 'MySQLi' not found). After doing that, it worked! Thank you Matt for your advice, it helped me.
Community
  • 1
  • 1
0

You are building your post body with:

let userEmail = userEmailTextField.text
let userPassword = userPasswordTextField.text

let postString = "email=\(userEmail)&password=\(userPassword)"

But userEmail and userPassword are optionals (because text is an optional). You should examine that postString and make sure it is what you intended, because I believe you meant to do:

let userEmail = userEmailTextField.text!
let userPassword = userPasswordTextField.text!

or

let userEmail = userEmailTextField.text ?? ""
let userPassword = userPasswordTextField.text ?? ""

Frankly, you should be percent escaping these, too (e.g. what if the password included a & or other reserved character in it?). For example, in Swift 2:

extension String {

    /// Percent escape value to be added to a HTTP request
    ///
    /// This percent-escapes all characters besize the alphanumeric character set and "-", ".", "_", and "*".
    /// This will also replace spaces with the "+" character as outlined in the application/x-www-form-urlencoded spec:
    ///
    /// http://www.w3.org/TR/html5/forms.html#application/x-www-form-urlencoded-encoding-algorithm
    ///
    /// - returns: Return percent escaped string.

    func stringByAddingPercentEncodingForFormUrlencoded() -> String? {
        let allowedCharacters = NSCharacterSet(charactersInString: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._* ")

        return stringByAddingPercentEncodingWithAllowedCharacters(allowedCharacters)?.stringByReplacingOccurrencesOfString(" ", withString: "+")
    }
}

And then:

let userEmail = userEmailTextField.text!.stringByAddingPercentEncodingForFormUrlencoded()
let userPassword = userPasswordTextField.text!.stringByAddingPercentEncodingForFormUrlencoded()

Or, if Swift 3:

extension String {

    /// Percent escape value to be added to a HTTP request
    ///
    /// This percent-escapes all characters besize the alphanumeric character set and "-", ".", "_", and "*".
    /// This will also replace spaces with the "+" character as outlined in the application/x-www-form-urlencoded spec:
    ///
    /// http://www.w3.org/TR/html5/forms.html#application/x-www-form-urlencoded-encoding-algorithm
    ///
    /// - returns: Return percent escaped string.

    func addingPercentEncodingForFormUrlencoded() -> String? {
        let allowedCharacters = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._* ")

        return addingPercentEncoding(withAllowedCharacters: allowedCharacters)?.replacingOccurrences(of: " ", with: "+")
    }
}

And

let userEmail = userEmailTextField.text!.addingPercentEncodingForFormUrlencoded()
let userPassword = userPasswordTextField.text!.addingPercentEncodingForFormUrlencoded()
Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Thanks a lot Rob! it was very helpful since I was getting strange characters on the email column, now I understand why. And this solved that. You are awesome! Just one more question, when I'm supposed to add the "extension String" ? should it be inside the class or outside? Thanks again! – Gaston Berenstein Nov 19 '15 at 20:40
  • Sorry for not responding to your question: You generally define it outside the class, a stand-alone extension that you might find yourself using elsewhere. – Rob Jun 24 '16 at 22:00