Android Code Snippet Register User example using OkHttpUtils2

Register User example using OkHttpUtils2

Demo1.png Demo2.png Demo3.png Demo4.png Demo5.png Demo6.png

Updates:
This project is deprecated. Please check User Login + MySQL PHP API
https://www.b4x.com/android/forum/threads/user-login-mysql-php-api.117826/

Introduction
This code snippet is based on the thread posted by KMatle in Tutorials & Examples. You can modify the layout and add in to your apps so that registered members can use your app by logging in using their user id and password.

How it works
This app starts by checking for connection by sending a request to the server and wait for a reply. The PHP script in the server will process the request and send back a JSON string. The screen will show "Connection success" if it is getting a response from the server.

Tap on the 'Register' button and the app will open up a new activity where information such as user id, password and email are required for the registration process. The data submitted will be stored in a MySQL database. An email will be sent to the user. If the user id or email is already registered before, a message will show "The user id '[YourUserID]' or email ([YourEmail]) is already in use". Open the email and click on the link to finish the registration process.

After successful register, you can press the 'Login' button to open up the Login activity. If you try to log in without activating your account at the first place, the app will show a message "Account is not activated!". Key in your user id and password and tap on the 'Login' button. If user id and password are incorrect, the app will show a message "Wrong User ID or Password!". If log in success, the app will show a message "Welcome, [YourFullName]" in a new activity showing a list of registered members in a listview.

This code snippet demonstrates of the usage of :
1. HttpUtils2 to connect to MySQL database located in a free hosting provider (using PHP web services and JSONParser)
2. Multiple Activity and Layout
3. SQL commands to Insert and Update records in MySQL database tables
4. Regular expression to check the email format
5. PHP Mail() function to send mail to the new member for activation and notify the administrator.
6. ListView for populating records stored in MySQL database table

Note that you can add more functions such as password hashing, retrieve forgotten password and using Captcha verification.

Version 1.1 (Update 07 July 2015)
- Rename a field in database table tbl_member from "status" to "reg_status"
- Added "(Online)" beside user name in listview
- Added a Log out button and signout.php
- Fixed signin.php showing 'null' user name

Version 1.2 (Update 10 Mar 2016)
- Retrieve Password
- Reset Password

Reupload PHP files (Update 19 Apr 2016)
Due to many confusion of register.php in a line of code somewhere in signup.php script, I have reuploaded PHP.zip in attachment. Sorry for the inconvenience.

Version 1.3 (Update 08 Feb 2019)
- Set targetSdkVersion=26
- Replaced HttpUtils2 with OkHttpUtils2
- Changed conflicting Job names with module names
- Added Change Password activity
- Removed Forgot Password activity
- Replaced MySQL functions in PHP script with MySQLi functions
- Added db.php in PHP script to store global variables

B4A Codes
B4X:
#Region  Project Attributes
    #ApplicationLabel: Demo
    #VersionCode: 4
    #VersionName: 1.3
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: portrait
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: False
#End Region

Sub Process_Globals
    Dim strURL As String = "http://demo.computerise.my/b4a/register-user-php/"    ' Remote / Production
    'Dim strURL As String = "http://192.168.43.191:8000/register-user-php/"        ' Local / Development
End Sub

Sub Globals
    Private Panel1 As Panel
    Private lblTitle As Label
    Private lblVersion As Label
    Private btnLogin As Button
    Private btnRegister As Button
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("frmStart")
    lblVersion.Text = "v 1.3"
    TestConnection
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub Activity_KeyPress(KeyCode As Int) As Boolean
    Dim Answ As Int
    Dim Txt As String

    If KeyCode = KeyCodes.KEYCODE_BACK Then    ' Checks if the KeyCode is BackKey
        Txt = "Do you really want to quit the program ?"
        Answ = Msgbox2(Txt, "A T T E N T I O N", "Yes", "", "No", Null) ' MessageBox
        If Answ = DialogResponse.POSITIVE Then    ' If return value is Yes then
            Return False    ' the Event will not be consumed     
        Else                ' we leave the program
            Return True        ' the Event will be consumed to avoid
        End If                ' leaving the program
    Else
        Return True            ' the Event will be consumed to avoid
    End If
End Sub

Sub lblTitle_Click
    Dim p As PhoneIntents
    Dim Url As String = "http://computerise.my"
    StartActivity(p.OpenBrowser(Url))
End Sub

Sub btnLogin_Click
    StartActivity("Login")
End Sub

Sub btnRegister_Click
    StartActivity("Register")
End Sub

Sub TestConnection
    Dim Connect As HttpJob
    Connect.Initialize("Connect", Me)
    Connect.Download(strURL & "connect.php")
    ProgressDialogShow("Connecting to server...")
End Sub

Sub JobDone (Job As HttpJob)
    ProgressDialogHide
    If Job.Success = True Then
        Dim ret As String
        ret = Job.GetString
        Dim parser As JSONParser
        parser.Initialize(ret) 
        If Job.JobName = "Connect" Then
            Dim act As String = parser.NextValue
            If act = "Connected" Then
                ToastMessageShow("Connection success", True)
            End If 
        End If
    Else
        ToastMessageShow("Error: " & Job.ErrorMessage, True)
    End If
    Job.Release
End Sub

B4X:
#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: False
#End Region

Sub Process_Globals

End Sub

Sub Globals
    Dim txtUserID As EditText
    Dim txtPassword As EditText
    Dim txtFullName As EditText
    Dim txtLocation As EditText
    Dim txtEmail As EditText
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("frmRegister")
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub btnRegister_Click
    Dim strUserID As String = txtUserID.Text.Trim
    If strUserID = "" Then
        Msgbox("Please enter User ID", "Error")
        Return
    End If
    Dim strPassword As String = txtPassword.Text.Trim
    If strPassword = "" Then
        Msgbox("Please enter Password", "Error")
        Return
    End If
    Dim strFullName As String = txtFullName.Text.Trim
    If strFullName = "" Then
        Msgbox("Please enter Full Name", "Error")
        Return
    End If
    Dim strLocation As String = txtLocation.Text.Trim
    If strLocation = "" Then
        Msgbox("Please enter Location", "Error")
        Return
    End If
    Dim strEmail As String = txtEmail.Text.Trim
    If strEmail = "" Then
        Msgbox("Please enter Email", "Error")
        Return
    End If
    If Validate_Email(strEmail) = False Then
        Msgbox("Email format is incorrect", "Error")
        Return
    End If

    Dim Job1 As HttpJob
    Job1.Initialize("Register", Me)
    Job1.Download2(Main.strURL & "signup.php", _
      Array As String("Action", "Register", _
      "UserID", txtUserID.Text, _
      "Password", txtPassword.Text, _
      "FullName", txtFullName.Text, _
      "Location", txtLocation.text, _
      "Email", txtEmail.Text))
    ProgressDialogShow("Connecting to server...")
End Sub

Sub JobDone (Job As HttpJob)
    ProgressDialogHide
    If Job.Success Then
        Dim parser As JSONParser
        Dim res As String
        Dim action As String
        res = Job.GetString 
        parser.Initialize(res)         
        Select Job.JobName
            Case "Register"
                action = parser.NextValue
                If action = "Mail" Then
                    Msgbox("An email was sent to " & txtEmail.Text & ". Please click on the link to finish registration", "Registration")
                    Activity.Finish
                Else If action = "MailInUse" Then
                    Msgbox("The user id '" & txtUserID.Text & "' or email (" & txtEmail.Text & ") is already in used", "Registration")
                Else
                    Msgbox("Server does not return expected result.", "Registration")
                End If
        End Select
    Else
        'Log("Error: " & Job.ErrorMessage)
        ToastMessageShow("Error: " & Job.ErrorMessage, True)
    End If
    Job.Release
End Sub

' // Source: https://www.b4x.com/android/forum/threads/validate-a-correctly-formatted-email-address.39803/
Sub Validate_Email(EmailAddress As String) As Boolean
    Dim MatchEmail As Matcher = Regex.Matcher("^(?i)[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])$", EmailAddress)

    If MatchEmail.Find = True Then
        'Log(MatchEmail.Match)
        Return True
    Else
        'Log("Oops, please double check your email address...")
        Return False
    End If
End Sub

B4X:
#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: False
#End Region

Sub Process_Globals
    Dim strUserID As String
    Dim strUserName As String
End Sub

Sub Globals
    Dim txtUserID As EditText
    Dim txtPassword As EditText
    Dim lblMessage As Label
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("frmLogin")
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub btnLogin_Click
    'Dim strUserID As String = txtUserID.Text.Trim
    lblMessage.Text = ""
    strUserID = txtUserID.Text.Trim
    If strUserID = "" Then
        Msgbox("Please enter User ID", "Error")
        Return
    End If
    Dim strPassword As String = txtPassword.Text.Trim
    If strPassword = "" Then
        Msgbox("Please enter Password", "Error")
        Return
    End If

    Dim Job2 As HttpJob
    Job2.Initialize("Login", Me)
    Job2.Download2(Main.strURL & "signin.php", _
    Array As String("user_id", strUserID, "password", strPassword))
    ProgressDialogShow("Connecting to server...")
End Sub

Sub JobDone (Job As HttpJob)
    ProgressDialogHide
    If Job.Success = True Then
        Dim ret As String
        Dim act As String 
        ret = Job.GetString  
        Dim parser As JSONParser
        parser.Initialize(ret) 
        act = parser.NextValue
        If act = "Not Found" Then
            ToastMessageShow("Login failed", True)
            lblMessage.Text = "Wrong User ID or Password!"
            lblMessage.TextColor = Colors.Red
        Else If act = "Not Activated" Then
            ToastMessageShow("Login failed", True)
            lblMessage.Text = "Account is not activated!"
            lblMessage.TextColor = Colors.Blue     
        Else If act = "Error" Then
            ToastMessageShow("Login failed", True)
            lblMessage.Text = "An error has occured!"
            lblMessage.TextColor = Colors.Red
        Else
            strUserName = act
            StartActivity("Member")
            Activity.Finish
        End If
    Else
        'Log("Error: " & Job.ErrorMessage)
        ToastMessageShow("Error: " & Job.ErrorMessage, True)
    End If
    Job.Release
End Sub

'Sub btnForgotMyPassword_Click
'    StartActivity("Forgot")
'End Sub

Sub btnResetMyPassword_Click
    StartActivity("Reset")
End Sub

B4X:
#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: False
#End Region

Sub Process_Globals

End Sub

Sub Globals
    Type TwoLines (First As String, Second As String)
    Private ListView1 As ListView
    Private btnLogout As Button
    Private lblMessage As Label
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("frmMember")
    lblMessage.Text = "Welcome, " & Login.strUserName
    LoadMemberList
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub LoadMemberList
    Dim Job3 As HttpJob
    Job3.Initialize("Member", Me)
    Job3.Download(Main.strURL & "member.php")
    ProgressDialogShow("Downloading list of registered members")
End Sub

Sub LogMeOut
    Dim Job4 As HttpJob
    Job4.Initialize("LogOut", Me)
    Job4.Download2(Main.strURL & "signout.php", _
    Array As String("user_id", Login.strUserID))
    ProgressDialogShow("Logging out...")
End Sub

Sub JobDone (Job As HttpJob)
    ProgressDialogHide
    If Job.Success = True Then
        Dim strReturn As String = Job.GetString
        Dim parser As JSONParser
        parser.Initialize(strReturn)
        If Job.JobName = "Member" Then
            Dim Members As List
            Dim strOnline As String
            Members = parser.NextArray 'returns a list with maps
            For i = 0 To Members.Size - 1
                Dim m As Map
                m = Members.Get(i)
                Dim TL As TwoLines
                If m.Get("online") = "Y" Then
                    strOnline = " (Online)"
                Else
                    strOnline = ""
                End If
                TL.First = m.Get("user_id") & strOnline
                TL.Second = m.Get("location")
                ListView1.AddTwoLines2(TL.First, TL.Second, TL)
            Next
        Else If Job.JobName = "LogOut" Then
            Dim act As String = parser.NextValue
            If act = "LoggedOut" Then
                ToastMessageShow("Logout successful", True)         
                StartActivity(Main)
                Activity.Finish
            End If         
        Else
            ToastMessageShow("Error: Invalid Value", True)
        End If
    Else
        'Log("Error: " & Job.ErrorMessage)
        ToastMessageShow("Error: " & Job.ErrorMessage, True)
    End If
    Job.Release
End Sub

Sub btnChangePassword_Click
    StartActivity("Change")
End Sub

Sub btnLogout_Click
    LogMeOut
End Sub

B4X:
#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: False
#End Region

Sub Process_Globals

End Sub

Sub Globals
    Private txtEmail As EditText
    Dim strEmail As String
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("frmReset")
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub btnSubmit_Click
    strEmail = txtEmail.Text.Trim
    If strEmail = "" Then
        Msgbox("Please enter Email", "Error")
        Return
    End If
    If Validate_Email(strEmail) = False Then
        Msgbox("Email format is incorrect", "Error")
        Return
    End If
    Dim Job5 As HttpJob
    Job5.Initialize("ResetPassword", Me)
    Job5.Download2(Main.strURL & "reset-password.php", _
      Array As String("Action", "RequestPasswordReset", _
      "Mail", strEmail))
    ProgressDialogShow("Connecting to server...")
End Sub

Sub JobDone (Job As HttpJob)
    ProgressDialogHide
    If Job.Success Then
    Dim res As String, action As String
        res = Job.GetString 
        Dim parser As JSONParser
        parser.Initialize(res)
        Select Job.JobName
            Case "ResetPassword"
                action = parser.NextValue
                If action = "ValidEmail" Then
                    Msgbox("An email was sent to " & strEmail & " to reset your password.", "Reset Password")             
                Else If action = "InvalidEmail" Then
                    Msgbox("The email is not registered in our database.", "Reset Password")
                End If
        End Select
    Else
        'Log("Error: " & Job.ErrorMessage)
        ToastMessageShow("Error: " & Job.ErrorMessage, True)
    End If
    Job.Release
End Sub

' // Source: https://www.b4x.com/android/forum/threads/validate-a-correctly-formatted-email-address.39803/
Sub Validate_Email(EmailAddress As String) As Boolean
    Dim MatchEmail As Matcher = Regex.Matcher("^(?i)[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])$", EmailAddress)

    If MatchEmail.Find = True Then
        'Log(MatchEmail.Match)
        Return True
    Else
        'Log("Oops, please double check your email address...")
        Return False
    End If
End Sub

B4X:
#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: False
#End Region

Sub Process_Globals

End Sub

Sub Globals
    Private txtEmail As EditText
    Private txtPassword1 As EditText
    Private txtPassword2 As EditText
    Private txtPassword3 As EditText
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("frmChange")
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub btnSubmit_Click
    Dim strEmail As String = txtEmail.Text.Trim
    If strEmail = "" Then
        Msgbox("Please enter Your Email", "Error")
        Return
    End If
    Dim strPassword1 As String = txtPassword1.Text.Trim
    If strPassword1 = "" Then
        Msgbox("Please enter Current Password", "Error")
        Return
    End If
    Dim strPassword2 As String = txtPassword2.Text.Trim
    If strPassword2 = "" Then
        Msgbox("Please enter New Password", "Error")
        Return
    End If
    Dim strPassword3 As String = txtPassword3.Text.Trim
    If strPassword3 = "" Then
        Msgbox("Please reenter New Password", "Error")
        Return
    End If
    If strPassword2 <> strPassword3 Then
        Msgbox("New Password not match", "Error")
        Return
    End If

    Dim Job6 As HttpJob
    Job6.Initialize("Change", Me)
    Job6.Download2(Main.strURL & "change-password.php", _
    Array As String("Email", strEmail, _
    "Password1", strPassword1, _
    "Password2", strPassword2))
    ProgressDialogShow("Connecting to server...")
End Sub

Sub JobDone (Job As HttpJob)
    ProgressDialogHide
    If Job.Success = True Then
        Dim ret As String
        Dim act As String
        ret = Job.GetString
        Dim parser As JSONParser
        parser.Initialize(ret)
        act = parser.NextValue
        If act = "Success" Then
            Msgbox("Password updated successfully!", "Change Password")
        Else If act = "Not Found" Then 
            Msgbox("Email or Password not correct!", "Change Password")
        Else If act = "Error" Or act = "Failed" Then
            Msgbox("An error occured!", "Change Password")
        Else ' Failed
            Msgbox("Uncaught error!", "Change Password")
        End If
    Else
        'Log("Error: " & Job.ErrorMessage)
        ToastMessageShow("Error: " & Job.ErrorMessage, True)
    End If
    Job.Release
End Sub

PHP Scripts

PHP:
<?php
    print json_encode("Connected");
?>

PHP:
<?php
    $host = "localhost";
    $user = "myuser";
    $pass = "mypassword";
    $db = "demo_b4a";
    $mysqli = new mysqli($host, $user, $pass, $db) or die($mysqli->error);

    // $server = "http://demo.computerise.my/b4a/";
    $server = "http://192.168.43.191:8000/register-user-php/";
    $admin = "[email protected]";
    $sender = "[email protected]";
?>

PHP:
<?php
    require 'db.php';
    try
    {
        if(!isset($_GET['Action']) || empty($_GET['Action']))
        {
            print json_encode("Parameter Error");
            exit;
        } 
        $action = $mysqli->escape_string($_GET["Action"]);

        switch ($action)
        {
            case "Register":
                if (!isset($_GET['UserID']) || empty($_GET['UserID']) ||
                    !isset($_GET['Email']) || empty($_GET['Email']) ||
                    !isset($_GET['Password']) || empty($_GET['Password']) ||
                    !isset($_GET['FullName']) || empty($_GET['FullName']) ||
                    !isset($_GET['Location']) || empty($_GET['Location']))
                {
                    print json_encode("Parameter Error");
                    exit;
                }
                $user = $mysqli->escape_string($_GET["UserID"]);
                $email = $mysqli->escape_string($_GET["Email"]);
                $password = $mysqli->escape_string($_GET["Password"]);
                $fullname = $mysqli->escape_string($_GET["FullName"]);
                $location = $mysqli->escape_string($_GET["Location"]);
                $sql = "SELECT * FROM tbl_member";
                $sql .= " WHERE email = '".$email."'";
                $sql .= " OR user_id = '".$user."'";
                $result = $mysqli->query($sql);
                $count = $result->num_rows;
                if ($count == 0)
                {
                    $randomnumber = mt_rand(111111, 999999);
                    $sql = "INSERT INTO tbl_member";
                    $sql .= " (user_id, user_name, pass_word,";
                    $sql .= " email, location,";
                    $sql .= " reg_status, reg_no, online)";
                    $sql .= " VALUES (";
                    $sql .= " '$user', '$fullname', '$password',";
                    $sql .= " '$email', '$location',";
                    $sql .= " 'M', $randomnumber, 'N')";
                    $mysqli->query($sql);
                    $to      = $email;
                    $subject = "B4A Register User Demo";
                    $message = "Hi ".$user.","."\r\n";
                    $message .= "Please click on this link to finish";
                    $message .= " the registration process:";
                    $message .= " ".$server."signup.php?Action=Mail";
                    $message .= "&Mail=".$email;
                    $message .= "&RegNo=".$randomnumber;
                    $message = wordwrap($message, 70, "\r\n");
                    $headers = "From: ".$sender."\r\n";
                    $headers .= "Reply-To: ".$sender."\r\n";
                    $headers .= "X-Mailer: PHP/".phpversion();

                    mail($to, $subject, $message, $headers);
                    // Notify me of new sign up
                    $to      = $admin;
                    $subject = "New member";
                    $message = "New member (".$user.") has signed up using our demo app.";
                    mail($to, $subject, $message, $headers);
                    print json_encode("Mail");
                }
                else
                    print json_encode("MailInUse");
                break;
            case "Mail":
                if (!isset($_GET['RegNo']) || empty($_GET['RegNo']) ||
                    !isset($_GET['Mail']) || empty($_GET['Mail']))
                {
                    print json_encode("Parameter Error");
                    exit;
                }     
                $regno = $mysqli->escape_string($_GET["RegNo"]);
                $mail = $mysqli->escape_string($_GET["Mail"]);
                $sql = "SELECT *";
                $sql .= " FROM tbl_member";
                $sql .= " WHERE email = '$mail'";
                $sql .= " AND reg_no = $regno";
                $sql .= " AND reg_status = 'M'";
                $result = $mysqli->query($sql);
                $count = $result->num_rows;
                if ($count == 0)
                {
                    print json_encode("This registration is not valid / email address is already registered");
                }
                else
                {
                    $sql = "UPDATE tbl_member";
                    $sql .= " SET reg_status = 'R'";
                    $sql .= " WHERE email = '$mail'";
                    $sql .= " AND reg_no = $regno";
                    $mysqli->query($sql);
                    echo("$mail is registered now :-)");
                    print json_encode("Success");
                }
                break;
            default:
                echo("Unauthorized action! Please use the app to register.");
        }
    }
    catch (Exception $e)
    {
        print json_encode("Failed");
        echo '<br />Caught exception: '.$e->getMessage()."\n";
    } 
?>

PHP:
<?php
    require 'db.php';
    try
    {
        if (!isset($_GET['user_id']) || empty($_GET['user_id']) ||
            !isset($_GET['password']) || empty($_GET['password']))
        {
            print json_encode("Parameter Error");
            exit;
        }  
        $uid = $mysqli->escape_string($_GET["user_id"]);
        $pwd = $mysqli->escape_string($_GET["password"]);

        $sql = "SELECT user_name, reg_status";
        $sql .= " FROM tbl_member";
        $sql .= " WHERE user_id = '".$uid."'";
        $sql .= " AND pass_word = '".$pwd."'";
        $result = $mysqli->query($sql);
        if ($mysqli->errno)
        {
            print json_encode("Error");
            echo "<br />".$mysqli->error;
            exit;
        }
        else
        {
            if ($result->num_rows == 0)
            {
                print json_encode("Not Found");
                exit;
            }
            $row = $result->fetch_row();
            if ($row[1] == "M")
            {
                print json_encode("Not Activated");
            }
            else
            {
                print json_encode($row[0]);
                $sql = "UPDATE tbl_member";
                $sql .= " SET Online = 'N'";
                $sql .= " WHERE now()-time_stamp > 60";      
                $mysqli->query($sql);
                $sql = "UPDATE tbl_member";
                $sql .= " SET logins = logins + 1,";
                $sql .= " Online = 'Y',";
                $sql .= " time_stamp = now()";
                $sql .= " WHERE user_id = '$uid'";
                $mysqli->query($sql);
            }
        }
    }
    catch (Exception $e)
    {
        print json_encode("Failed");
        echo '<br />Caught exception: '.$e->getMessage()."\n";
    }
?>

PHP:
<?php
    require 'db.php';
    try
    {
        if(!isset($_GET['user_id']) || empty($_GET['user_id']))
        {
            print json_encode("Parameter Error");
            exit;
        }  
        $uid = $mysqli->escape_string($_GET["user_id"]);
        $sql = "SELECT online";
        $sql .= " FROM tbl_member";
        $sql .= " WHERE user_id = '$uid'";
        $result = $mysqli->query($sql);
        $count = $result->num_rows;
        if ($count == 0)
        {
              print json_encode("NotMember");
        }
        else
        {
            $sql = "UPDATE tbl_member";
            $sql .= " SET online = 'N'";
            $sql .= " WHERE user_id = '".$uid."'";
            $mysqli->query($sql);
            print json_encode("LoggedOut");
        }
    }
    catch (Exception $e)
    {
        print json_encode("Failed");
        echo '<br />Caught exception: '.$e->getMessage()."\n";
    }
?>

PHP:
<?php
    require 'db.php';
    try
    {
        $sql = "SELECT user_id, location, online";
        $sql .= " FROM tbl_member";
        $sql .= " ORDER BY id DESC";
        $result = $mysqli->query($sql);
        if ($mysqli->errno)
        {
            header("HTTP/1.1 500 Internal Server Error");
            echo $sql.'\n';
            echo $mysqli->error;
        }
        else
        {
            $rows = array();
            while ($row = $result->fetch_assoc())
            {
                $rows[] = $row;
            }
            print json_encode($rows);
        }
    }
    catch (Exception $e)
    {
        print json_encode("Failed");
        echo '<br />Caught exception: '.$e->getMessage()."\n";
    }
?>

PHP:
<?php
require 'db.php';
try
{
    if (!isset($_GET['Email']) || empty($_GET['Email']) ||
        !isset($_GET['Password1']) || empty($_GET['Password1']) ||
        !isset($_GET['Password2']) || empty($_GET['Password2']))
    {
        print json_encode("Parameter Error");
        exit;
    }
    $email = $mysqli->escape_string($_GET["Email"]);
    $password1 = $mysqli->escape_string($_GET["Password1"]);
    $password2 = $mysqli->escape_string($_GET["Password2"]);
    $sql = "SELECT * FROM tbl_member";
    $sql .= " WHERE email = '".$email."'";
    $sql .= " AND pass_word = '".$password1."'";
    $result = $mysqli->query($sql);
    $count = $result->num_rows;
    if ($count == 0)
    {  
        print json_encode("Not Found");
        echo("<br />User not found or incorrect password");
    }
    else
    {
        $sql = "UPDATE tbl_member";
        $sql .= " SET pass_word = '".$password2."'";
        $sql .= " WHERE email = '".$email."'";
        $sql .= " AND pass_word = '".$password1."'";
        $mysqli->query($sql);  
        print json_encode("Success");
        echo("<br />$email has been updated");
    }
}
catch (Exception $e)
{
    print json_encode("Failed");
    echo '<br />Caught exception: '.$e->getMessage()."\n";
}  
?>

PHP:
<?php
    require 'db.php';
    try
    {
        if(!isset($_GET['Action']) || empty($_GET['Action']))
        {
            print json_encode("Parameter Error");
            exit;
        }
        $action = $mysqli->escape_string($_GET["Action"]);
        switch ($action)
        {
            case "RequestPasswordReset":
                if(!isset($_GET['Mail']) || empty($_GET['Mail']))
                {
                    print json_encode("Parameter Error");
                    exit;
                }      
                $email = $mysqli->escape_string($_GET["Mail"]);
                $sql = "SELECT user_name";
                $sql .= " FROM tbl_member";
                $sql .= " WHERE email = '" . $email . "'";
                $result = $mysqli->query($sql);
                if ($mysqli->errno)
                {
                    print json_encode("MySQL_Error");
                    echo "<br />MySQL_Error: ".$mysqli->error;
                    exit;
                }
                $count = $result->num_rows;
                if ($count == 0)
                {
                    print json_encode("InvalidEmail");
                    exit;
                }
                else
                {
                    // Generate a random code and update to reg_no
                    $verify_code = mt_rand(100000, 999999);
                    $row = $result->fetch_row();
                    $username = $row[0];
                    $sql = "UPDATE tbl_member";
                    $sql .= " SET reg_no = '" . $verify_code . "'";
                    $sql .= " WHERE email = '" . $email . "'";
                    $mysqli->query($sql);
                    if ($mysqli->errno)
                    {
                        print json_encode("MySQL_Error");
                        echo "<br />MySQL_Error: ".$mysqli->error;
                        exit;
                    }
                    // Send email to user to confirm the reset
                    $to      = $email;
                    $subject = 'Request to reset your password';
                    $message = "Hi " . $username . ",\r\n";
                    $message .= "We have received a request from you to reset your password.\r\n";
                    $message .= "If this action is not requested by you,";
                    $message .= " please ignore this email.\r\n";
                    $message .= "Otherwise, click the link below:\r\n";
                    $message .= $server."reset-password.php?Action=ConfirmPasswordReset";
                    $message .= "&Mail=".$email;
                    $message .= "&Code=".$verify_code . "\r\n\r\n";
                    $message .= "If not working, please copy the link to your browser.\r\n\r\n";
                    $message .= "Regards,\r\n";
                    $message .= "Aeric";
                    $message = wordwrap($message, 70, "\r\n");
                    $headers = "From: ".$sender."\r\n";
                    $headers .= "Reply-To: ".$sender."\r\n";
                    $headers .= "X-Mailer: PHP/" . phpversion();
                    mail($to, $subject, $message, $headers);
                    print json_encode("ValidEmail");
                }
            break;
        case "ConfirmPasswordReset":
            if (!isset($_GET['Mail']) || empty($_GET['Mail']) ||
                !isset($_GET['Code']) || empty($_GET['Code']))
            {
                print json_encode("Parameter Error");
                exit;
            }
            $email = $mysqli->escape_string($_GET["Mail"]);
            $code = $mysqli->escape_string($_GET["Code"]);
            $sql = "SELECT user_name";
            $sql .= " FROM tbl_member";
            $sql .= " WHERE email = '" . $email . "'";
            $sql .= " AND reg_no = " . $code;
            $result = $mysqli->query($sql);
            if ($mysqli->errno)
            {
                print json_encode("MySQL_Error");
                echo "<br />MySQL_Error: ".$mysqli->error;
                exit;
            }
            $count = $result->num_rows;
            if ($count == 0)
            {
                print json_encode("InvalidEmailOrCode");
                exit;
            }
            // Generate a default password randomly (e.g. pw1234)
            // You may use other method to generate a more complex password with alphanumeric
            $rand_number = mt_rand(1000, 9999);
            $default = "pw" . $rand_number;
            $row = $result->fetch_row();
            $username = $row[0];
            $sql = "UPDATE tbl_member";
            $sql .= " SET pass_word = '" . $default . "'";
            $sql .= " WHERE email = '" . $email . "'";
            $mysqli->query($sql);
            if ($mysqli->errno)
            {
                print json_encode("MySQL_Error");
                echo "<br />MySQL_Error: ".$mysqli->error;
                exit;
            }
            $to      = $email;
            $subject = 'Your New Password';
            $message = "Hi ".$username.",\r\n";
            $message .= "Your password has been reset.";
            $message .= " Please use your new password to log in.\r\n";
            $message .= "Password: " . $default;
            $message = wordwrap($message, 70, "\r\n");
            $headers = "From: ".$sender."\r\n";
            $headers .= "Reply-To: ".$sender."\r\n";
            $headers .= "X-Mailer: PHP/" . phpversion();
            mail($to, $subject, $message, $headers);
            //print json_encode("PasswordChanged");
            echo "Your password has been reset.<br />Your new password is sent to $email.";
            break;
        default:
            echo("Unauthorized action! Please use the app to reset your password.");
        }
    }
    catch (Exception $e)
    {  
        print json_encode("Failed");
        echo '<br />Caught exception: '.$e->getMessage()."\n";
    }
?>

Code also available in Github

pyhoon/Register-User-B4A

pyhoon/Register-User-PHP
 

Attachments

  • RegisterUser1.1.zip
    36.8 KB · Views: 2,244
  • RegisterUser1.3.zip
    43.3 KB · Views: 1,317
  • register-user-php.zip
    6 KB · Views: 1,264
Last edited:

Hedgar

Member
Hi. Thanks For This Example. how comes the password is not case sensitive and how can we fix this.
as in i tried login in the the same password but different cases. surprisingly, all of them work
 

aeric

Expert
Licensed User
Longtime User
Hi. Thanks For This Example. how comes the password is not case sensitive and how can we fix this.
as in i tried login in the the same password but different cases. surprisingly, all of them work
I never tested on the password case. Maybe you can find on Internet how to handle the case incensitive.
 

toby

Well-Known Member
Licensed User
Longtime User
<?php
$host = "localhost";
$user = "myuser";
$pass = "mypassword";
$db = "demo_b4a";
$mysqli = new mysqli($host, $user, $pass, $db) or die($mysqli->error);

// $server = "http://demo.computerise.my/b4a/";
$server = "http://192.168.43.191:8000/register-user-php/";
$admin = "[email protected]";
$sender = "[email protected]";
?>

Great tutorial indeed! My current app is similar to your tutorial in that the database login username/password are stored on the server in php file. Now I need to make it more secure to prevent from unauthorized access to mysql database. Anyone could access a url like https://mywebsite.com/updateCustomer. How do I make sure that the request is from my b4a app and nothing else?

Thank you in advance for your help!
 

aeric

Expert
Licensed User
Longtime User
Check my latest example where I use API key.
 

CyberDroidWare

Member
Licensed User
Register User example using OKHttpUtils2

View attachment 77216 View attachment 77217 View attachment 77218 View attachment 77219 View attachment 77220 View attachment 77221

Introduction
This code snippet is based on the thread posted by KMatle in Tutorials & Examples. You can modify the layout and add in to your apps so that registered members can use your app by logging in using their user id and password.

How it works
This app starts by checking for connection by sending a request to the server and wait for a reply. The PHP script in the server will process the request and send back a JSON string. The screen will show "Connection success" if it is getting a response from the server.

Tap on the 'Register' button and the app will open up a new activity where information such as user id, password and email are required for the registration process. The data submitted will be stored in a MySQL database. An email will be sent to the user. If the user id or email is already registered before, a message will show "The user id '[YourUserID]' or email ([YourEmail]) is already in use". Open the email and click on the link to finish the registration process.

After successful register, you can press the 'Login' button to open up the Login activity. If you try to log in without activating your account at the first place, the app will show a message "Account is not activated!". Key in your user id and password and tap on the 'Login' button. If user id and password are incorrect, the app will show a message "Wrong User ID or Password!". If log in success, the app will show a message "Welcome, [YourFullName]" in a new activity showing a list of registered members in a listview.

This code snippet demonstrates of the usage of :
1. HttpUtils2 to connect to MySQL database located in a free hosting provider (using PHP web services and JSONParser)
2. Multiple Activity and Layout
3. SQL commands to Insert and Update records in MySQL database tables
4. Regular expression to check the email format
5. PHP Mail() function to send mail to the new member for activation and notify the administrator.
6. ListView for populating records stored in MySQL database table

Note that you can add more functions such as password hashing, retrieve forgotten password and using Captcha verification.

Version 1.1 (Update 07 July 2015)
- Rename a field in database table tbl_member from "status" to "reg_status"
- Added "(Online)" beside user name in listview
- Added a Log out button and signout.php
- Fixed signin.php showing 'null' user name

Version 1.2 (Update 10 Mar 2016)
- Retrieve Password
- Reset Password

Reupload PHP files (Update 19 Apr 2016)
Due to many confusion of register.php in a line of code somewhere in signup.php script, I have reuploaded PHP.zip in attachment. Sorry for the inconvenience.

Version 1.3 (Update 08 Feb 2019)
- Set targetSdkVersion=26
- Replaced HttpUtils2 with OKHttpUtils2
- Changed conflicting Job names with module names
- Added Change Password activity
- Removed Forgot Password activity
- Replaced MySQL functions in PHP script with MySQLi functions
- Added db.php in PHP script to store global variables

B4A Codes
B4X:
#Region  Project Attributes
    #ApplicationLabel: Demo
    #VersionCode: 4
    #VersionName: 1.3
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: portrait
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: False
#End Region

Sub Process_Globals
    Dim strURL As String = "http://demo.computerise.my/b4a/register-user-php/"    ' Remote / Production
    'Dim strURL As String = "http://192.168.43.191:8000/register-user-php/"        ' Local / Development
End Sub

Sub Globals
    Private Panel1 As Panel
    Private lblTitle As Label
    Private lblVersion As Label
    Private btnLogin As Button
    Private btnRegister As Button
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("frmStart")
    lblVersion.Text = "v 1.3"
    TestConnection
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub Activity_KeyPress(KeyCode As Int) As Boolean
    Dim Answ As Int
    Dim Txt As String

    If KeyCode = KeyCodes.KEYCODE_BACK Then    ' Checks if the KeyCode is BackKey
        Txt = "Do you really want to quit the program ?"
        Answ = Msgbox2(Txt, "A T T E N T I O N", "Yes", "", "No", Null) ' MessageBox
        If Answ = DialogResponse.POSITIVE Then    ' If return value is Yes then
            Return False    ' the Event will not be consumed       
        Else                ' we leave the program
            Return True        ' the Event will be consumed to avoid
        End If                ' leaving the program
    Else
        Return True            ' the Event will be consumed to avoid
    End If
End Sub

Sub lblTitle_Click
    Dim p As PhoneIntents
    Dim Url As String = "http://computerise.my"
    StartActivity(p.OpenBrowser(Url))
End Sub

Sub btnLogin_Click
    StartActivity("Login")
End Sub

Sub btnRegister_Click
    StartActivity("Register")
End Sub

Sub TestConnection
    Dim Connect As HttpJob
    Connect.Initialize("Connect", Me)
    Connect.Download(strURL & "connect.php")
    ProgressDialogShow("Connecting to server...")
End Sub

Sub JobDone (Job As HttpJob)
    ProgressDialogHide
    If Job.Success = True Then
        Dim ret As String
        ret = Job.GetString
        Dim parser As JSONParser
        parser.Initialize(ret)   
        If Job.JobName = "Connect" Then
            Dim act As String = parser.NextValue
            If act = "Connected" Then
                ToastMessageShow("Connection success", True)
            End If   
        End If
    Else
        ToastMessageShow("Error: " & Job.ErrorMessage, True)
    End If
    Job.Release
End Sub

B4X:
#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: False
#End Region

Sub Process_Globals

End Sub

Sub Globals
    Dim txtUserID As EditText
    Dim txtPassword As EditText
    Dim txtFullName As EditText
    Dim txtLocation As EditText
    Dim txtEmail As EditText
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("frmRegister")
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub btnRegister_Click
    Dim strUserID As String = txtUserID.Text.Trim
    If strUserID = "" Then
        Msgbox("Please enter User ID", "Error")
        Return
    End If
    Dim strPassword As String = txtPassword.Text.Trim
    If strPassword = "" Then
        Msgbox("Please enter Password", "Error")
        Return
    End If
    Dim strFullName As String = txtFullName.Text.Trim
    If strFullName = "" Then
        Msgbox("Please enter Full Name", "Error")
        Return
    End If
    Dim strLocation As String = txtLocation.Text.Trim
    If strLocation = "" Then
        Msgbox("Please enter Location", "Error")
        Return
    End If
    Dim strEmail As String = txtEmail.Text.Trim
    If strEmail = "" Then
        Msgbox("Please enter Email", "Error")
        Return
    End If
    If Validate_Email(strEmail) = False Then
        Msgbox("Email format is incorrect", "Error")
        Return
    End If

    Dim Job1 As HttpJob
    Job1.Initialize("Register", Me)
    Job1.Download2(Main.strURL & "signup.php", _
      Array As String("Action", "Register", _
      "UserID", txtUserID.Text, _
      "Password", txtPassword.Text, _
      "FullName", txtFullName.Text, _
      "Location", txtLocation.text, _
      "Email", txtEmail.Text))
    ProgressDialogShow("Connecting to server...")
End Sub

Sub JobDone (Job As HttpJob)
    ProgressDialogHide
    If Job.Success Then
        Dim parser As JSONParser
        Dim res As String
        Dim action As String
        res = Job.GetString   
        parser.Initialize(res)           
        Select Job.JobName
            Case "Register"
                action = parser.NextValue
                If action = "Mail" Then
                    Msgbox("An email was sent to " & txtEmail.Text & ". Please click on the link to finish registration", "Registration")
                    Activity.Finish
                Else If action = "MailInUse" Then
                    Msgbox("The user id '" & txtUserID.Text & "' or email (" & txtEmail.Text & ") is already in used", "Registration")
                Else
                    Msgbox("Server does not return expected result.", "Registration")
                End If
        End Select
    Else
        'Log("Error: " & Job.ErrorMessage)
        ToastMessageShow("Error: " & Job.ErrorMessage, True)
    End If
    Job.Release
End Sub

' // Source: https://www.b4x.com/android/forum/threads/validate-a-correctly-formatted-email-address.39803/
Sub Validate_Email(EmailAddress As String) As Boolean
    Dim MatchEmail As Matcher = Regex.Matcher("^(?i)[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])$", EmailAddress)

    If MatchEmail.Find = True Then
        'Log(MatchEmail.Match)
        Return True
    Else
        'Log("Oops, please double check your email address...")
        Return False
    End If
End Sub

B4X:
#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: False
#End Region

Sub Process_Globals
    Dim strUserID As String
    Dim strUserName As String
End Sub

Sub Globals
    Dim txtUserID As EditText
    Dim txtPassword As EditText
    Dim lblMessage As Label
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("frmLogin")
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub btnLogin_Click
    'Dim strUserID As String = txtUserID.Text.Trim
    lblMessage.Text = ""
    strUserID = txtUserID.Text.Trim
    If strUserID = "" Then
        Msgbox("Please enter User ID", "Error")
        Return
    End If
    Dim strPassword As String = txtPassword.Text.Trim
    If strPassword = "" Then
        Msgbox("Please enter Password", "Error")
        Return
    End If

    Dim Job2 As HttpJob
    Job2.Initialize("Login", Me)
    Job2.Download2(Main.strURL & "signin.php", _
    Array As String("user_id", strUserID, "password", strPassword))
    ProgressDialogShow("Connecting to server...")
End Sub

Sub JobDone (Job As HttpJob)
    ProgressDialogHide
    If Job.Success = True Then
        Dim ret As String
        Dim act As String   
        ret = Job.GetString    
        Dim parser As JSONParser
        parser.Initialize(ret)   
        act = parser.NextValue
        If act = "Not Found" Then
            ToastMessageShow("Login failed", True)
            lblMessage.Text = "Wrong User ID or Password!"
            lblMessage.TextColor = Colors.Red
        Else If act = "Not Activated" Then
            ToastMessageShow("Login failed", True)
            lblMessage.Text = "Account is not activated!"
            lblMessage.TextColor = Colors.Blue       
        Else If act = "Error" Then
            ToastMessageShow("Login failed", True)
            lblMessage.Text = "An error has occured!"
            lblMessage.TextColor = Colors.Red
        Else
            strUserName = act
            StartActivity("Member")
            Activity.Finish
        End If
    Else
        'Log("Error: " & Job.ErrorMessage)
        ToastMessageShow("Error: " & Job.ErrorMessage, True)
    End If
    Job.Release
End Sub

'Sub btnForgotMyPassword_Click
'    StartActivity("Forgot")
'End Sub

Sub btnResetMyPassword_Click
    StartActivity("Reset")
End Sub

B4X:
#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: False
#End Region

Sub Process_Globals

End Sub

Sub Globals
    Type TwoLines (First As String, Second As String)
    Private ListView1 As ListView
    Private btnLogout As Button
    Private lblMessage As Label
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("frmMember")
    lblMessage.Text = "Welcome, " & Login.strUserName
    LoadMemberList
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub LoadMemberList
    Dim Job3 As HttpJob
    Job3.Initialize("Member", Me)
    Job3.Download(Main.strURL & "member.php")
    ProgressDialogShow("Downloading list of registered members")
End Sub

Sub LogMeOut
    Dim Job4 As HttpJob
    Job4.Initialize("LogOut", Me)
    Job4.Download2(Main.strURL & "signout.php", _
    Array As String("user_id", Login.strUserID))
    ProgressDialogShow("Logging out...")
End Sub

Sub JobDone (Job As HttpJob)
    ProgressDialogHide
    If Job.Success = True Then
        Dim strReturn As String = Job.GetString
        Dim parser As JSONParser
        parser.Initialize(strReturn)
        If Job.JobName = "Member" Then
            Dim Members As List
            Dim strOnline As String
            Members = parser.NextArray 'returns a list with maps
            For i = 0 To Members.Size - 1
                Dim m As Map
                m = Members.Get(i)
                Dim TL As TwoLines
                If m.Get("online") = "Y" Then
                    strOnline = " (Online)"
                Else
                    strOnline = ""
                End If
                TL.First = m.Get("user_id") & strOnline
                TL.Second = m.Get("location")
                ListView1.AddTwoLines2(TL.First, TL.Second, TL)
            Next
        Else If Job.JobName = "LogOut" Then
            Dim act As String = parser.NextValue
            If act = "LoggedOut" Then
                ToastMessageShow("Logout successful", True)           
                StartActivity(Main)
                Activity.Finish
            End If           
        Else
            ToastMessageShow("Error: Invalid Value", True)
        End If
    Else
        'Log("Error: " & Job.ErrorMessage)
        ToastMessageShow("Error: " & Job.ErrorMessage, True)
    End If
    Job.Release
End Sub

Sub btnChangePassword_Click
    StartActivity("Change")
End Sub

Sub btnLogout_Click
    LogMeOut
End Sub

B4X:
#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: False
#End Region

Sub Process_Globals

End Sub

Sub Globals
    Private txtEmail As EditText
    Dim strEmail As String
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("frmReset")
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub btnSubmit_Click
    strEmail = txtEmail.Text.Trim
    If strEmail = "" Then
        Msgbox("Please enter Email", "Error")
        Return
    End If
    If Validate_Email(strEmail) = False Then
        Msgbox("Email format is incorrect", "Error")
        Return
    End If
    Dim Job5 As HttpJob
    Job5.Initialize("ResetPassword", Me)
    Job5.Download2(Main.strURL & "reset-password.php", _
      Array As String("Action", "RequestPasswordReset", _
      "Mail", strEmail))
    ProgressDialogShow("Connecting to server...")
End Sub

Sub JobDone (Job As HttpJob)
    ProgressDialogHide
    If Job.Success Then
    Dim res As String, action As String
        res = Job.GetString   
        Dim parser As JSONParser
        parser.Initialize(res)
        Select Job.JobName
            Case "ResetPassword"
                action = parser.NextValue
                If action = "ValidEmail" Then
                    Msgbox("An email was sent to " & strEmail & " to reset your password.", "Reset Password")               
                Else If action = "InvalidEmail" Then
                    Msgbox("The email is not registered in our database.", "Reset Password")
                End If
        End Select
    Else
        'Log("Error: " & Job.ErrorMessage)
        ToastMessageShow("Error: " & Job.ErrorMessage, True)
    End If
    Job.Release
End Sub

' // Source: https://www.b4x.com/android/forum/threads/validate-a-correctly-formatted-email-address.39803/
Sub Validate_Email(EmailAddress As String) As Boolean
    Dim MatchEmail As Matcher = Regex.Matcher("^(?i)[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])$", EmailAddress)

    If MatchEmail.Find = True Then
        'Log(MatchEmail.Match)
        Return True
    Else
        'Log("Oops, please double check your email address...")
        Return False
    End If
End Sub

B4X:
#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: False
#End Region

Sub Process_Globals

End Sub

Sub Globals
    Private txtEmail As EditText
    Private txtPassword1 As EditText
    Private txtPassword2 As EditText
    Private txtPassword3 As EditText
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("frmChange")
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub btnSubmit_Click
    Dim strEmail As String = txtEmail.Text.Trim
    If strEmail = "" Then
        Msgbox("Please enter Your Email", "Error")
        Return
    End If
    Dim strPassword1 As String = txtPassword1.Text.Trim
    If strPassword1 = "" Then
        Msgbox("Please enter Current Password", "Error")
        Return
    End If
    Dim strPassword2 As String = txtPassword2.Text.Trim
    If strPassword2 = "" Then
        Msgbox("Please enter New Password", "Error")
        Return
    End If
    Dim strPassword3 As String = txtPassword3.Text.Trim
    If strPassword3 = "" Then
        Msgbox("Please reenter New Password", "Error")
        Return
    End If
    If strPassword2 <> strPassword3 Then
        Msgbox("New Password not match", "Error")
        Return
    End If

    Dim Job6 As HttpJob
    Job6.Initialize("Change", Me)
    Job6.Download2(Main.strURL & "change-password.php", _
    Array As String("Email", strEmail, _
    "Password1", strPassword1, _
    "Password2", strPassword2))
    ProgressDialogShow("Connecting to server...")
End Sub

Sub JobDone (Job As HttpJob)
    ProgressDialogHide
    If Job.Success = True Then
        Dim ret As String
        Dim act As String
        ret = Job.GetString
        Dim parser As JSONParser
        parser.Initialize(ret)
        act = parser.NextValue
        If act = "Success" Then
            Msgbox("Password updated successfully!", "Change Password")
        Else If act = "Not Found" Then   
            Msgbox("Email or Password not correct!", "Change Password")
        Else If act = "Error" Or act = "Failed" Then
            Msgbox("An error occured!", "Change Password")
        Else ' Failed
            Msgbox("Uncaught error!", "Change Password")
        End If
    Else
        'Log("Error: " & Job.ErrorMessage)
        ToastMessageShow("Error: " & Job.ErrorMessage, True)
    End If
    Job.Release
End Sub

PHP Scripts

PHP:
<?php
    print json_encode("Connected");
?>

PHP:
<?php
    $host = "localhost";
    $user = "myuser";
    $pass = "mypassword";
    $db = "demo_b4a";
    $mysqli = new mysqli($host, $user, $pass, $db) or die($mysqli->error);

    // $server = "http://demo.computerise.my/b4a/";
    $server = "http://192.168.43.191:8000/register-user-php/";
    $admin = "[email protected]";
    $sender = "[email protected]";
?>

PHP:
<?php
    require 'db.php';
    try
    {
        if(!isset($_GET['Action']) || empty($_GET['Action']))
        {
            print json_encode("Parameter Error");
            exit;
        }   
        $action = $mysqli->escape_string($_GET["Action"]);

        switch ($action)
        {
            case "Register":
                if (!isset($_GET['UserID']) || empty($_GET['UserID']) ||
                    !isset($_GET['Email']) || empty($_GET['Email']) ||
                    !isset($_GET['Password']) || empty($_GET['Password']) ||
                    !isset($_GET['FullName']) || empty($_GET['FullName']) ||
                    !isset($_GET['Location']) || empty($_GET['Location']))
                {
                    print json_encode("Parameter Error");
                    exit;
                }
                $user = $mysqli->escape_string($_GET["UserID"]);
                $email = $mysqli->escape_string($_GET["Email"]);
                $password = $mysqli->escape_string($_GET["Password"]);
                $fullname = $mysqli->escape_string($_GET["FullName"]);
                $location = $mysqli->escape_string($_GET["Location"]);
                $sql = "SELECT * FROM tbl_member";
                $sql .= " WHERE email = '".$email."'";
                $sql .= " OR user_id = '".$user."'";
                $result = $mysqli->query($sql);
                $count = $result->num_rows;
                if ($count == 0)
                {
                    $randomnumber = mt_rand(111111, 999999);
                    $sql = "INSERT INTO tbl_member";
                    $sql .= " (user_id, user_name, pass_word,";
                    $sql .= " email, location,";
                    $sql .= " reg_status, reg_no, online)";
                    $sql .= " VALUES (";
                    $sql .= " '$user', '$fullname', '$password',";
                    $sql .= " '$email', '$location',";
                    $sql .= " 'M', $randomnumber, 'N')";
                    $mysqli->query($sql);
                    $to      = $email;
                    $subject = "B4A Register User Demo";
                    $message = "Hi ".$user.","."\r\n";
                    $message .= "Please click on this link to finish";
                    $message .= " the registration process:";
                    $message .= " ".$server."signup.php?Action=Mail";
                    $message .= "&Mail=".$email;
                    $message .= "&RegNo=".$randomnumber;
                    $message = wordwrap($message, 70, "\r\n");
                    $headers = "From: ".$sender."\r\n";
                    $headers .= "Reply-To: ".$sender."\r\n";
                    $headers .= "X-Mailer: PHP/".phpversion();

                    mail($to, $subject, $message, $headers);
                    // Notify me of new sign up
                    $to      = $admin;
                    $subject = "New member";
                    $message = "New member (".$user.") has signed up using our demo app.";
                    mail($to, $subject, $message, $headers);
                    print json_encode("Mail");
                }
                else
                    print json_encode("MailInUse"); 
                break;
            case "Mail":
                if (!isset($_GET['RegNo']) || empty($_GET['RegNo']) ||
                    !isset($_GET['Mail']) || empty($_GET['Mail']))
                {
                    print json_encode("Parameter Error");
                    exit;
                }       
                $regno = $mysqli->escape_string($_GET["RegNo"]);
                $mail = $mysqli->escape_string($_GET["Mail"]);
                $sql = "SELECT *";
                $sql .= " FROM tbl_member";
                $sql .= " WHERE email = '$mail'";
                $sql .= " AND reg_no = $regno";
                $sql .= " AND reg_status = 'M'";
                $result = $mysqli->query($sql);
                $count = $result->num_rows; 
                if ($count == 0)
                {
                    print json_encode("This registration is not valid / email address is already registered");
                }
                else
                {
                    $sql = "UPDATE tbl_member";
                    $sql .= " SET reg_status = 'R'";
                    $sql .= " WHERE email = '$mail'";
                    $sql .= " AND reg_no = $regno";
                    $mysqli->query($sql);
                    echo("$mail is registered now :-)");
                    print json_encode("Success");
                }
                break;
            default:
                echo("Unauthorized action! Please use the app to register.");
        }
    }
    catch (Exception $e)
    {
        print json_encode("Failed");
        echo '<br />Caught exception: '.$e->getMessage()."\n";
    }   
?>

PHP:
<?php
    require 'db.php';
    try
    {
        if (!isset($_GET['user_id']) || empty($_GET['user_id']) ||
            !isset($_GET['password']) || empty($_GET['password']))
        {
            print json_encode("Parameter Error");
            exit;
        }    
        $uid = $mysqli->escape_string($_GET["user_id"]);
        $pwd = $mysqli->escape_string($_GET["password"]);

        $sql = "SELECT user_name, reg_status";
        $sql .= " FROM tbl_member";
        $sql .= " WHERE user_id = '".$uid."'";
        $sql .= " AND pass_word = '".$pwd."'";
        $result = $mysqli->query($sql);
        if ($mysqli->errno)
        {
            print json_encode("Error");
            echo "<br />".$mysqli->error;
            exit;
        }
        else
        {
            if ($result->num_rows == 0)
            {
                print json_encode("Not Found");
                exit;
            }
            $row = $result->fetch_row();
            if ($row[1] == "M")
            {
                print json_encode("Not Activated");
            }
            else
            {
                print json_encode($row[0]);
                $sql = "UPDATE tbl_member";
                $sql .= " SET Online = 'N'";
                $sql .= " WHERE now()-time_stamp > 60";        
                $mysqli->query($sql);
                $sql = "UPDATE tbl_member";
                $sql .= " SET logins = logins + 1,";
                $sql .= " Online = 'Y',";
                $sql .= " time_stamp = now()";
                $sql .= " WHERE user_id = '$uid'";
                $mysqli->query($sql);
            }
        }
    }
    catch (Exception $e)
    {
        print json_encode("Failed");
        echo '<br />Caught exception: '.$e->getMessage()."\n";
    }
?>

PHP:
<?php
    require 'db.php';
    try
    {
        if(!isset($_GET['user_id']) || empty($_GET['user_id']))
        {
            print json_encode("Parameter Error");
            exit;
        }    
        $uid = $mysqli->escape_string($_GET["user_id"]);
        $sql = "SELECT online";
        $sql .= " FROM tbl_member";
        $sql .= " WHERE user_id = '$uid'";
        $result = $mysqli->query($sql);
        $count = $result->num_rows;
        if ($count == 0)
        {
              print json_encode("NotMember");
        }
        else
        {
            $sql = "UPDATE tbl_member";
            $sql .= " SET online = 'N'";
            $sql .= " WHERE user_id = '".$uid."'";
            $mysqli->query($sql);
            print json_encode("LoggedOut");
        }
    }
    catch (Exception $e)
    {
        print json_encode("Failed");
        echo '<br />Caught exception: '.$e->getMessage()."\n";
    }
?>

PHP:
<?php
    require 'db.php';
    try
    {
        $sql = "SELECT user_id, location, online";
        $sql .= " FROM tbl_member";
        $sql .= " ORDER BY id DESC";
        $result = $mysqli->query($sql);
        if ($mysqli->errno)
        {
            header("HTTP/1.1 500 Internal Server Error");
            echo $sql.'\n';
            echo $mysqli->error;
        }
        else
        {
            $rows = array();
            while ($row = $result->fetch_assoc())
            {
                $rows[] = $row;
            }
            print json_encode($rows);
        }
    }
    catch (Exception $e)
    {
        print json_encode("Failed");
        echo '<br />Caught exception: '.$e->getMessage()."\n";
    }
?>

PHP:
<?php
require 'db.php';
try
{
    if (!isset($_GET['Email']) || empty($_GET['Email']) ||
        !isset($_GET['Password1']) || empty($_GET['Password1']) ||
        !isset($_GET['Password2']) || empty($_GET['Password2']))
    {
        print json_encode("Parameter Error");
        exit;
    }
    $email = $mysqli->escape_string($_GET["Email"]);
    $password1 = $mysqli->escape_string($_GET["Password1"]);
    $password2 = $mysqli->escape_string($_GET["Password2"]);
    $sql = "SELECT * FROM tbl_member";
    $sql .= " WHERE email = '".$email."'";
    $sql .= " AND pass_word = '".$password1."'";
    $result = $mysqli->query($sql);
    $count = $result->num_rows;
    if ($count == 0)
    {    
        print json_encode("Not Found");
        echo("<br />User not found or incorrect password");
    }
    else
    {
        $sql = "UPDATE tbl_member";
        $sql .= " SET pass_word = '".$password2."'";
        $sql .= " WHERE email = '".$email."'";
        $sql .= " AND pass_word = '".$password1."'";
        $mysqli->query($sql);    
        print json_encode("Success");
        echo("<br />$email has been updated");
    }
}
catch (Exception $e)
{
    print json_encode("Failed");
    echo '<br />Caught exception: '.$e->getMessage()."\n";
}    
?>

PHP:
<?php
    require 'db.php';
    try
    {
        if(!isset($_GET['Action']) || empty($_GET['Action']))
        {
            print json_encode("Parameter Error");
            exit;
        }
        $action = $mysqli->escape_string($_GET["Action"]);
        switch ($action)
        {
            case "RequestPasswordReset":
                if(!isset($_GET['Mail']) || empty($_GET['Mail']))
                {
                    print json_encode("Parameter Error");
                    exit;
                }        
                $email = $mysqli->escape_string($_GET["Mail"]);
                $sql = "SELECT user_name";
                $sql .= " FROM tbl_member";
                $sql .= " WHERE email = '" . $email . "'";
                $result = $mysqli->query($sql);
                if ($mysqli->errno)
                {
                    print json_encode("MySQL_Error");
                    echo "<br />MySQL_Error: ".$mysqli->error;
                    exit;
                }
                $count = $result->num_rows;
                if ($count == 0)
                {
                    print json_encode("InvalidEmail");
                    exit;
                }
                else
                {
                    // Generate a random code and update to reg_no
                    $verify_code = mt_rand(100000, 999999);
                    $row = $result->fetch_row();
                    $username = $row[0];
                    $sql = "UPDATE tbl_member";
                    $sql .= " SET reg_no = '" . $verify_code . "'";
                    $sql .= " WHERE email = '" . $email . "'";
                    $mysqli->query($sql);
                    if ($mysqli->errno)
                    {
                        print json_encode("MySQL_Error");
                        echo "<br />MySQL_Error: ".$mysqli->error;
                        exit;
                    }
                    // Send email to user to confirm the reset
                    $to      = $email;
                    $subject = 'Request to reset your password';
                    $message = "Hi " . $username . ",\r\n";
                    $message .= "We have received a request from you to reset your password.\r\n";
                    $message .= "If this action is not requested by you,";
                    $message .= " please ignore this email.\r\n";
                    $message .= "Otherwise, click the link below:\r\n";
                    $message .= $server."reset-password.php?Action=ConfirmPasswordReset";
                    $message .= "&Mail=".$email;
                    $message .= "&Code=".$verify_code . "\r\n\r\n";
                    $message .= "If not working, please copy the link to your browser.\r\n\r\n";
                    $message .= "Regards,\r\n";
                    $message .= "Aeric";
                    $message = wordwrap($message, 70, "\r\n");
                    $headers = "From: ".$sender."\r\n";
                    $headers .= "Reply-To: ".$sender."\r\n";
                    $headers .= "X-Mailer: PHP/" . phpversion();
                    mail($to, $subject, $message, $headers);
                    print json_encode("ValidEmail");
                }
            break;
        case "ConfirmPasswordReset":
            if (!isset($_GET['Mail']) || empty($_GET['Mail']) ||
                !isset($_GET['Code']) || empty($_GET['Code']))
            {
                print json_encode("Parameter Error");
                exit;
            }
            $email = $mysqli->escape_string($_GET["Mail"]);
            $code = $mysqli->escape_string($_GET["Code"]);
            $sql = "SELECT user_name";
            $sql .= " FROM tbl_member";
            $sql .= " WHERE email = '" . $email . "'";
            $sql .= " AND reg_no = " . $code;
            $result = $mysqli->query($sql);
            if ($mysqli->errno)
            {
                print json_encode("MySQL_Error");
                echo "<br />MySQL_Error: ".$mysqli->error;
                exit;
            }
            $count = $result->num_rows;
            if ($count == 0)
            {
                print json_encode("InvalidEmailOrCode");
                exit;
            }
            // Generate a default password randomly (e.g. pw1234)
            // You may use other method to generate a more complex password with alphanumeric
            $rand_number = mt_rand(1000, 9999);
            $default = "pw" . $rand_number;
            $row = $result->fetch_row();
            $username = $row[0];
            $sql = "UPDATE tbl_member";
            $sql .= " SET pass_word = '" . $default . "'";
            $sql .= " WHERE email = '" . $email . "'";
            $mysqli->query($sql);
            if ($mysqli->errno)
            {
                print json_encode("MySQL_Error");
                echo "<br />MySQL_Error: ".$mysqli->error;
                exit;
            }
            $to      = $email;
            $subject = 'Your New Password';
            $message = "Hi ".$username.",\r\n";
            $message .= "Your password has been reset.";
            $message .= " Please use your new password to log in.\r\n";
            $message .= "Password: " . $default;
            $message = wordwrap($message, 70, "\r\n");
            $headers = "From: ".$sender."\r\n";
            $headers .= "Reply-To: ".$sender."\r\n";
            $headers .= "X-Mailer: PHP/" . phpversion();
            mail($to, $subject, $message, $headers);
            //print json_encode("PasswordChanged");
            echo "Your password has been reset.<br />Your new password is sent to $email.";
            break;
        default:
            echo("Unauthorized action! Please use the app to reset your password.");
        }
    }
    catch (Exception $e)
    {    
        print json_encode("Failed");
        echo '<br />Caught exception: '.$e->getMessage()."\n";
    }
?>

Code also available in Github

pyhoon/Register-User-B4A

pyhoon/Register-User-PHP
Good work. I know this is a demo but just to help other developers, you do need to consider Cybersecurity and privacy when using any Web call in your App. Be sure to use properly configured HTTP pinning secure connection to avoid both breaches and/or MITM interception/hacking.

Simon

MITM attack reveals plain text details:
GET /b4a/register-user-php/connect.php HTTP/1.1
Host: demo.computerise.my
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/3.5.0

HTTP/1.1 200 OK
Date: Sat, 21 Nov 2020 07:12:49 GMT
Server: Apache
X-Powered-By: PHP/7.2.34
Upgrade: h2,h2c
Connection: Upgrade, Keep-Alive
Vary: Accept-Encoding
Keep-Alive: timeout=5, max=100
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8

b
"Connected"
0

GET /b4a/register-user-php/signin.php?user_id=122&password=eee HTTP/1.1
Host: demo.computerise.my
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/3.5.0
 

aeric

Expert
Licensed User
Longtime User
Good work. I know this is a demo but just to help other developers, you do need to consider Cybersecurity and privacy when using any Web call in your App. Be sure to use properly configured HTTP pinning secure connection to avoid both breaches and/or MITM interception/hacking.

Simon

MITM attack reveals plain text details:
GET /b4a/register-user-php/connect.php HTTP/1.1
Host: demo.computerise.my
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/3.5.0

HTTP/1.1 200 OK
Date: Sat, 21 Nov 2020 07:12:49 GMT
Server: Apache
X-Powered-By: PHP/7.2.34
Upgrade: h2,h2c
Connection: Upgrade, Keep-Alive
Vary: Accept-Encoding
Keep-Alive: timeout=5, max=100
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8

b
"Connected"
0

GET /b4a/register-user-php/signin.php?user_id=122&password=eee HTTP/1.1
Host: demo.computerise.my
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/3.5.0
I agree with you that security need to be considered. If you read from the start, you will notice that when I posted this project, I was just started with B4A, Httputils and PHP back to 5 years ago. That’s why I recommended to take a look of my latest project in post #84.
 

softmicro

Member
Licensed User
Longtime User
Hello,
I have tested your application version 1.3 and it works correctly with your external address for the registration of a new user when sending the email, and confirm there with the confirmation link.
But I do not achieve the same with the application on my local server, although the rest works, because I do not know what email address you have to put in order to send the request and access the new user authorization link.
Can you help me to achieve the goal of local use?
Is it possible to use this option in this condition?

I'm using google translate, sorry if the translation is not correct.
Thanks
 

softmicro

Member
Licensed User
Longtime User
Hello Aeric
I am on my PC and I have opened XAMPP for Apache and phpmyadmin.
I have also used Visual Studio to analyze and edit the PHP.

I have even edited both PHP and B4A to my language and all the functions that do not include the sending of confirmation email work correctly.
I cannot understand how the recipient email data should be completed in this internal use case.
Later, I will find out how to do all this from my server at Hostgator.
Thanks
 

aeric

Expert
Licensed User
Longtime User
Hello Aeric
I am on my PC and I have opened XAMPP for Apache and phpmyadmin.
I have also used Visual Studio to analyze and edit the PHP.

I have even edited both PHP and B4A to my language and all the functions that do not include the sending of confirmation email work correctly.
I cannot understand how the recipient email data should be completed in this internal use case.
Later, I will find out how to do all this from my server at Hostgator.
Thanks
I am not sure how it is done using XAMPP but using Laragon is easy to test the email function. It can also create the email as txt file inside a mail folder.
 

softmicro

Member
Licensed User
Longtime User
Hi
Excellent use of the laragon application instead of xampp to send the mail needed to register a new user or act on the password.
I also added that it allows access to unsafe applications in the security property in the gmail account that I had used for this occasion.
Thank you very much for your advice.

Additional topic, on Friday August 13, I have sent you the completed form to your COMPUTERISE page to get in touch with you to request the provision of different software that you offer.

But I have not received any response or acceptance of my submission.
Will I have to resubmit my contact request?
Thanks
 

aeric

Expert
Licensed User
Longtime User
Additional topic, on Friday August 13, I have sent you the completed form to your COMPUTERISE page to get in touch with you to request the provision of different software that you offer.

But I have not received any response or acceptance of my submission.
Will I have to resubmit my contact request?
Not sure it went to junk folder. You can send me a private message.
 
Top