Create a new Android Studio project (Either Basic or Empty Activity) and name it “InputValidation” and click on Next
Choose the form factor that your app will run on. You can leave it on the default settings
You should redirect to this interface
// Copy and paste the following code into “MainActivity.java”.
// MainActivity.java
package com.example.inputvalidation;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MainActivity extends AppCompatActivity {
//Button showButton;
EditText input;
TextView showInput;
DatabaseHelper dbhelper;
SQLiteDatabase db;
public static final String TB_NAME="usertable";
//public static String result = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//showButton = (Button) findViewById(R.id.button_1);
input = (EditText) findViewById(R.id.editText);
showInput = (TextView) findViewById(R.id.textView2);
dbhelper=new DatabaseHelper(this, TB_NAME, null, 1);
db=dbhelper.getWritableDatabase();
}
public void onClick(View view) {
switch (view.getId()) {
case R.id.button_1:
showResult(input.getText().toString());
break;
case R.id.button_2:
if (!isValidSearch(input.getText().toString())) {
input.setError("Invalid Search");
}
else {
showResult(input.getText().toString());
}
break;
case R.id.button_3:
Cursor cursor;
String m_argv[] = {input.getText().toString()};
cursor=db.rawQuery("SELECT * FROM usertable WHERE _id= ? ",m_argv );
cursor.moveToFirst();
String result = null;
while (!cursor.isAfterLast()) {
result += "id:" + cursor.getInt(0) + "\r\n" + "user:" + cursor.getString(1) + "\r\n" + "pass:" + cursor.getString(2) + "\r\n";
cursor.moveToNext();
}
showInput.setText(result);
cursor.close();
break;
case R.id.button_4:
showResult("");
break;
}
}
public void showResult(String info){
if(info == null || info.length() <= 0)
showInput.setText("Please input:");
else{
Cursor cursor;
cursor = db.rawQuery("SELECT * FROM usertable WHERE _id='" + info + "'", null);
cursor.moveToFirst();
String result = null;
while (!cursor.isAfterLast()) {
result += "id:" + cursor.getInt(0) + "\r\n" + "user:" + cursor.getString(1) + "\r\n" + "pass:" + cursor.getString(2) + "\r\n";
cursor.moveToNext();
}
showInput.setText(result);
cursor.close();
}
}
private boolean isValidSearch(String name) {
//String NAME_PATTERN = "^\\W$";
String NAME_PATTERN = "^^[0-9]*$";
Pattern pattern = Pattern.compile(NAME_PATTERN);
Matcher matcher = pattern.matcher(name);
//System.out.println(matcher.matches());
return matcher.matches();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Right-click on com.example.inputvalidation in the project side-bar on the left and select New->Java Class
Create a new file named "DatabaseHelper" and press enter,
Repeat same process for "FirstFragment.java" and "SecondFragment.java".
Copy the following code into the newly created “DatabaseHelper.java”, "FirstFragment.java", "SecondFragment.java", and "activity_main.xml"
// Copy the following code into the newly created “DatabaseHelper.java”.
// DatabaseHelper.java
package com.example.inputvalidation;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DatabaseHelper extends SQLiteOpenHelper {
public static int num = 0;
public static final String TB_NAME="usertable";
public static final String ID="_id";
public static final String USERNAME="username";
public static final String PASSWORD="password";
public static final int del = 2;
public DatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory,
int version) {
super(context, name, factory, version);
// TODO Auto-generated constructor stub
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS "+TB_NAME+" ("+ID+" INTEGER PRIMARY KEY,"+USERNAME+" VARCHAR,"+PASSWORD+" VARCHAR )");
// create the java statement
String count = "SELECT count(*) FROM usertable";
Cursor mcursor = db.rawQuery(count, null);
mcursor.moveToFirst();
int icount = mcursor.getInt(0);
if(icount==0) {
// execute the query, and get a java resultset
db.execSQL("INSERT INTO " + TB_NAME + "(" + USERNAME + "," + PASSWORD + ") VALUES" + "('Mike','1234')");
db.execSQL("INSERT INTO " + TB_NAME + "(" + USERNAME + "," + PASSWORD + ") VALUES" + "('John','3456')");
db.execSQL("INSERT INTO " + TB_NAME + "(" + USERNAME + "," + PASSWORD + ") VALUES" + "('Nick','6789')");
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(DatabaseHelper.class.getName(),
"Upgrading database from version " + oldVersion + " to "
+ newVersion + ", which will destroy all old data");
//db.execSQL("DROP TABLE IF EXISTS " + TABLE_COMMENTS);
onCreate(db);
}
@Override
public void onOpen(SQLiteDatabase db) {
// TODO Auto-generated method stub
super.onOpen(db);
}
}
// Copy the following code into the newly created “FirstFragment.java”.
// FirstFragment.java
package com.example.inputvalidation;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.navigation.fragment.NavHostFragment;
import com.example.inputvalidation.databinding.FragmentFirstBinding;
public class FirstFragment extends Fragment {
private FragmentFirstBinding binding;
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState
) {
binding = FragmentFirstBinding.inflate(inflater, container, false);
return binding.getRoot();
}
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding.buttonFirst.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
NavHostFragment.findNavController(FirstFragment.this)
.navigate(R.id.action_FirstFragment_to_SecondFragment);
}
});
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}
// Copy the following code into the newly created “SecondFragment.java”.
// SecondFragment.java
package com.example.inputvalidation;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.navigation.fragment.NavHostFragment;
import com.example.inputvalidation.databinding.FragmentSecondBinding;
public class SecondFragment extends Fragment {
private FragmentSecondBinding binding;
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState
) {
binding = FragmentSecondBinding.inflate(inflater, container, false);
return binding.getRoot();
}
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding.buttonSecond.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
NavHostFragment.findNavController(SecondFragment.this)
.navigate(R.id.action_SecondFragment_to_FirstFragment);
}
});
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}
//Copy the following code into “activity_main.xml”. Make sure to click on the “Text” tab at the bottom left of the “activity_main.xml” window
//activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView android:text="Please input:" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textView" />
<EditText
android:layout_width="300dp"
android:layout_height="wrap_content"
android:id="@+id/editText"
android:layout_below="@+id/textView"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_below="@+id/editText"
android:id="@+id/linearLayout">
<Button
style="?android:attr/buttonStyleSmall"
android:layout_width="92dp"
android:layout_height="wrap_content"
android:text="Unsecure search"
android:id="@+id/button_1"
android:layout_below="@+id/editText"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:onClick="onClick"/>
<Button
style="?android:attr/buttonStyleSmall"
android:layout_width="61dp"
android:layout_height="wrap_content"
android:text="Se_Search1"
android:id="@+id/button_2"
android:onClick="onClick"/>
<Button
style="?android:attr/buttonStyleSmall"
android:layout_width="82dp"
android:layout_height="wrap_content"
android:text="Se_Search2"
android:id="@+id/button_3"
android:onClick="onClick"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Refresh"
android:id="@+id/button_4"
android:layout_below="@+id/linearLayout"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:onClick="onClick" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:id="@+id/textView2"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignRight="@+id/linearLayout"
android:layout_alignEnd="@+id/linearLayout"
android:layout_alignParentBottom="true"
android:layout_below="@+id/linearLayout" />
</RelativeLayout>
The AVD will look like this interface
The 3 search buttons allow the user to search the database for the id inputted to display their search results, and the refresh button allows the user to refresh their screen.
The data stored in the database should be the following:
nullid: 1
user: Mike
pass: 1234
nullid: 2
user: John
pass: 3456
nullid: 3
user: Nick
pass: 6789
When the user inputs 1 or 2 or 3 into the input field and presses any of the search buttons the application will display the respective information for the id provided. However, if the user was to use an invalid input, such as “ 1’ or ‘1’ = ‘1 “ and press the insecure search button, then the invalid tautology input will result in the whole database returning, as the invalid input always returns true.
If the user was to input the same input, but press the se_search1 button, it would result in an invalid input error message as the se_search1 button is protected by RegEx, which is written to only allow access to the database if the input is composed of only characters 0-9.
The se_search2 button is also protected against invalid inputs; however, instead of using RegEx, the se_search2 button is protected by the parameterized statement. In the case of this se_search2 button, when invalid input is used, nothing happens, as the input is rejected and no error message is given.