Write rawQuery with Java to stop sql injection - android

I am trying to prove that my current code stops prevents sql injection. At the same time I am trying to learn to write a rawQuery that uses ? for a place holder.
My Table is as follows below
public static final String TABLE_NAME = "masterPW";
public static final String Col_ID = "ID";
public static final String Col_MPW = "mpw";
When the MainActivity starts it checks to see if the Col_MPW has data or not by calling the onLoad method that goes to DBHelper Class code below
private void onLoad(){
dbHelper = new DBHelper( this );
str = dbHelper.getCol_MPW();
// Line of code above calls getCol_MPW method in DBHelper
// And DBHwlper RETURNS str Variable with the Master Password
//============================================================
if (str == null || str.isEmpty()) {
etPW.requestFocus();
btnSave.setVisibility( View.VISIBLE );
System.out.println( "I am NULL" );
} else {
setTitle( "Enter Password "+str );
tvCPW.setVisibility( View.INVISIBLE );
etCPW.setVisibility( View.INVISIBLE );
btnSave.setVisibility( View.INVISIBLE );
btnEnter.setVisibility( View.VISIBLE );
System.out.println( "Im NOT NULL "+str );
}
}
Ok so now we will say the password has been created and when the user enters the password to go to the next activity we call the onLoad grab the value in the TABLE and return it to the MainActivity and preform validation
the code below is in the DBHelper and returns a string for validation
public String getCol_MPW(){
String str = null;
db = getReadableDatabase();
String q = "SELECT mpw FROM masterPW";
//String q = "SELECT * FROM masterPW";
//String ov = etPW.getText().toString();
//Cursor cursor = db.rawQuery("SELECT mpw "+"FROM masterPW"+"WHERE mpw = ? ",new String[]{ov};
// The line of CODE above fails even when I replase ov with the PASSWORD
//=================================================================
Cursor cursor = db.rawQuery(q,null);
if(cursor.moveToFirst()){
str = cursor.getString(cursor.getColumnIndex(Col_MPW));
}
cursor.close();
db.close();
return str;
}
The str that is returnd to the MainActivity is then validated with this code
public void onEnter(View view) {
// Will use REGEX here so matches is ok
// But with NO REGEX -> MUST <- use equals
//if (str.matches( etPW.getText().toString().trim() )) {
if(str.equals(etPW.getText().toString().trim())){
etPW.setText( "" );
str = "";
Intent intent = new Intent( MainActivity.this, PageTwo.class );
startActivity( intent );
} else {
Toast.makeText( MainActivity.this, "Incorrect Password", Toast.LENGTH_LONG ).show();
etPW.requestFocus();
}
}
My Code in DBHelper public String getCol_MPW() has some of my non productive attempts at NON sql injection code commented out. That said I have also tried various sql injection techniques to get past my validation none would work.
So I would still like to have some guidance on how to implement better rawQuery methods to prevent sql injection? After the password I need to add other data to the database. I have looked at prepared statements and binding but if I can not implement this with a table that has only one row ever I see no point in going further

Related

Implementing better search from sqlite android

I am currently using a SearchView to take input and whenever the input changes i call searchVideo()
this is my searchVideo function :
public void searchVideo(String s)
{
videos.clear();
SQLiteDatabase sqLiteDatabase = getActivity().openOrCreateDatabase("CodifyData", MODE_PRIVATE, null);
String sql = "SELECT * FROM appdata_videos WHERE subcode='"+dbName+"' AND title LIKE '%"+s+"%'";
Cursor c = sqLiteDatabase.rawQuery(sql,null);
int idID = c.getColumnIndex("id");
int linkID = c.getColumnIndex("link");
int titleID = c.getColumnIndex("title");
while(c.moveToNext())
{
videos.add(new VideoDataModel(c.getString(idID), c.getString(titleID), c.getString(linkID)));
}
c.close();
videoAdapter.notifyDataSetChanged();
}
But when user inputs two words and those two works are contained by the title but not next to each other or in a way they are input by the user, the search fails, so what can i do to make this better, don't need a complicated solution but something simpler and easier to implement.
split your string by space to get array of words
and concat the values with query like that:
String[] splitedValues = str.split("\\s+");
String query="SELECT * FROM appdata_videos WHERE subcode='"+dbName+"' ";
for(int i=0;i<splitedValues .length;i++){
query+="AND title LIKE '%"+splitedValues[i]+"%' ";
}

Android Textview Showing Null in output

I am getting a problem in android textview.
I am simply setting text on the android textview like below
pAmount.setText("Rs." + receiptAmount + "/-");
but is showing null in the text
System.out.println("receiptAmount ====>"+ receiptAmount );
I had tried to print the value of receiptAmount to check whether, the value is null or not.
But, It is showing the right value in the log.
What is the issue does any body have any idea.
similarly , other texview are showing the null value in the same activity.
TextView pAmount= (TextView) findViewById(R.id.amount);
1.Call the set text After Declaring the above line in Oncreate.
2.get the Proper data in receiptAmount. Your Problem Solved
pAmount.setText("Rs." + receiptAmount + "/-");
public void FeeGetFeeTypes(String studentId, String fee_slotid) {
// TODO Auto-generated method stub
ArrayList<String> arrayList_FeeType=new ArrayList<String>();
ArrayList<String> arrayList_FeeTypeAmount=new ArrayList<String>();
try{
SQLiteDatabase db = this.getReadableDatabase();
final String MY_QUERY = "select * from feetype where student_id=? and slot_id=?";
Cursor res = db.rawQuery(MY_QUERY, new String[]{ studentId, fee_slotid });
res.moveToFirst();
while (res.isAfterLast() == false){
arrayList_FeeType.add(res.getString(res
.getColumnIndex(FEE_TYPE_COLUMN_FEETYPE)));
arrayList_FeeTypeAmount.add(res.getString(res
.getColumnIndex(FEE_TYPE_COLUMN_FEETYPEAMOUNT)));
}
if(arrayList_FeeType.size()>0){
PrintActivity.sendFeeType(arrayList_FeeType, arrayList_FeeTypeAmount);
}
}
catch(Exception e){
e.printStackTrace();
}
}
This is the code that is resulting the null values. When the data is large, I get out of memory exception

Xamarin.Android - Challenge with SQLite ORM queries

I've been working with Xamarin for a few weeks now and i'm trying to find the best practices for using SQLite ORM queries.I have a log in page which is launched first before users can access the app.I have the database created before this first activity comes to the screen and administrator log in details inserted into the user's table as soon as the tables are created.The point is,the admin is meant to log in and import an xml file containing all of the other user's personal information.This information is read from the file and saved to sqlite as well.
Next,the other users can log in after their details have been imported and saved successfully.My challenge is,at the point of logging in,i would like to verify the details as follows:
1.Compare the entered username with a single username from the db
**2.Check the password entered to see if it matches the username entered **
I'm currently using a select query to pull up all the passwords from the database,before comparing the two strings(from the db and from the edit text field).If it's a large db however,reading all the data will be quite expensive.How do i go about this?
How do i also look up the password for that username?
Below is my code:
namespace sample.NameSpace
{
[Activity (MainLauncher = true)]
public class MainActivity : Activity
{
Button login = FindViewById<Button> (Resource.Id.login);
try{
login.Click += (object sender, EventArgs e) => {
if (TextUtils.IsEmpty(userName.Text.ToString())) {
makeToast();
} else if (TextUtils.IsEmpty(password.Text.ToString())) {
makeToast();
} else {
returningUser = userName.Text.ToString().Trim();
returningUserPassword = password.Text.ToString().Trim();
}
//Check to see if the name is in the db already
List<string> allUsers = GetAllUserNames();
//Loop through the list of names and compare the retrieved username with the name entered in the text field
string retrievedDbName ="";
foreach(string name in allUsers )
{
retrievedDbName = name .Trim();
}
//Verify name
if(retrievedDbName .Equals(returningUser))
{
Toast.MakeText(this,
"Login Successful !", ToastLength.Short).Show();
Intent intent = new Intent (this, typeof(HomeActivity));
StartActivity (intent);
}
else
{
Toast.MakeText(this, "User Name or Password does not match", ToastLength.Short).Show();
}
};
} catch(Exception e){
logger.Exception (this, e);
}
public List<string>GetAllUserNames()
{
List<UserInfoTable> allUserNames = new List<UserInfoTable> ();
allUserNames = dataManager.GetSingleUserName ();
string name = "";
foreach(var UserName in allUserNames)
{
Console.WriteLine ("Usernames from db :" + name.ToString());
}
return allUserNames;
}
Then the DataManager class:
public List<UserInfoTable> GetSingleUserName()
{
UserInfoTable user = new UserInfoTable ();
using (var db = dbHandler.getUserDatabaseConnection ()) {
var userName = db.Query<UserInfoTable> ("select * from UserInfoTable where user_name = ?", user.USER_NAME);
return userName;
}
}
public bool CheckLogin(string user, string password)
{
bool valid = false;
using (var db = dbHandler.getUserDatabaseConnection ()) {
var user = db.Query<UserInfoTable> ("select * from UserInfoTable where user_name = ? and password = ?", user, password);
if (user != null) valid = true;
}
return valid;
}

Update on Content Provider does nothing

I'm trying to make an Android app to help people suffering from headaches. I have a sqlite database to store the crisis, and users can add a crisis by pushing a button. The same button is used to indicate the crisis is over. In other words, when you feel the headache coming, you push the button ; then, when it's over, you press it again and the application updates the corresponding entry whith the "end date".
But if my insert does well, my update does not update at all. Here is how it is supposed to work :
I first retrieve the latest entry in my database (which is the one with the greatest id), then I get the actual date, and put it in a ContentValue. Finally I update the entry.
Here is the button code :
public void onClickStartStop(View v){
Log.v("andromed", "Starting/Stopping crisis");
String d = new Date().toString();
ContentValues cv = new ContentValues();
String user_info = "";
String[] projection = {CriseContract.COLUMN_NAME_CRISE_ID, CriseContract.COLUMN_NAME_CRISE_DEBUT,CriseContract.COLUMN_NAME_CRISE_FIN};
Cursor criseCursor = getContentResolver().query(CriseContract.CONTENT_URI, projection,"SELECT MAX("+CriseContract.COLUMN_NAME_CRISE_ID+") FROM "+CriseContract.TABLE_NAME, null, null);
Log.v("andromed",""+criseCursor.getCount());
if(criseCursor.getCount()>=0){
while(criseCursor.moveToNext()){
String date_fin = criseCursor.getString(criseCursor.getColumnIndex(CriseContract.COLUMN_NAME_CRISE_FIN));
if(!(date_fin==(null))){
Log.v("andromed","Date exists "+date_fin);
user_info = "Crise enregistrée";
cv.put(CriseContract.COLUMN_NAME_CRISE_DEBUT, d);
Uri u = getContentResolver().insert(CriseContract.CONTENT_URI, cv);
}else{
String date_deb = criseCursor.getString(criseCursor.getColumnIndex(CriseContract.COLUMN_NAME_CRISE_DEBUT));
if(date_deb==null){
Log.v("andromed","No date in db");
user_info = "Crise enregistrée";
cv.put(CriseContract.COLUMN_NAME_CRISE_DEBUT, d);
Uri u = getContentResolver().insert(CriseContract.CONTENT_URI, cv);
}else{
Log.v("andromed", "Need to close the crisis");
cv.put(CriseContract.COLUMN_NAME_CRISE_FIN, d);
int tmp = getMaxId();
String where = CriseContract.COLUMN_NAME_CRISE_ID+"="+tmp;
String[] st = {""+tmp};
int nup = getContentResolver().update(CriseContract.CONTENT_URI,cv, where, null);
Log.v("andromed", nup+" rows updated");
user_info = "Crise terminée";
}
}
}
}else{
user_info = "Erreur lors de la lecture";
}
Toast t = Toast.makeText(getApplicationContext(),user_info, Toast.LENGTH_LONG);
t.show();
}
(Don't mind the Log and the toast stuff, just for me).
Here is my function to retrieve the maximum id :
private int getMaxId(){
String[] projection = {CriseContract.COLUMN_NAME_CRISE_ID};
String selection = "SELECT MAX("+CriseContract.COLUMN_NAME_CRISE_ID+") FROM "+CriseContract.TABLE_NAME;
Cursor c = getContentResolver().query(CriseContract.CONTENT_URI, projection, selection, null, null);
Log.v("andromed", ""+c.getCount());
int maxid=-1;
if(c!=null){
while(c.moveToNext()){
maxid = c.getInt(c.getColumnIndex(CriseContract.COLUMN_NAME_CRISE_ID));
}
}
Log.v("andromed", "Greatest id in table Crise : "+maxid);
return maxid;
}
And of course, my contract class :
public final static class CriseContract{
public static final String AUTHORITY = "com.piertris.andromed";
public static final String BASE_PATH = "database";
public static final Uri CONTENT_URI = Uri.parse("content://"+AUTHORITY+"/"+BASE_PATH);
public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE+"/"+BASE_PATH;
public static final String CONTENT_ITEM_TYPE= ContentResolver.CURSOR_ITEM_BASE_TYPE+"/andromed";
public static final String TABLE_NAME = "crises";
public static final String COLUMN_NAME_CRISE_ID = "criseid";
public static final String COLUMN_NAME_CRISE_DEBUT = "date_debut";
public static final String COLUMN_NAME_CRISE_FIN = "date_fin";
public static final String COLUMN_NAME_INTENSITE = "intensite";
public static final String COLUMN_NAME_SYMPTOM = "symptome";
public static final String COLUMN_NAME_MED = "prise_med";
public static final String COLUMN_NAME_MEDS = "type_med";
public static final String COLUMN_NAME_AURA = "aura";
public static final String COLUMN_NAME_COMMENT = "comments";
}
When I try to end the current crisis, my Logcat tells me that 0 rows were updated.
Thanks to SO, I already corrected other problems due to a wrong use of the function, but this time, the only link I found was this one : Android content provider not updating database and the OP just added a comment saying he updated his ContentProvider, but nothing more.
What am I doing wrong ? Did I "misnamed" my column names ? Do I misuse the update function ?
Thanks for your help.
EDIT
Thanks to Jozua, I realized that I didn't implement the update function in my ContentProvider file. Alright, I feel extremely dumb right now. I'll keep you informed on how does it work once the update() function is written.
Once again, thanks Jozua.
Alright, I kind of solved the problem, but in a really bad way.
Considering the fact that I retrieve the crisis just once in order to add almost everything that is needed but the beginning date and the id, I simply turned my update() request into a delete() followed by an update() in which I pass a ContentValue containing the values of the row I previously deleted.
I know it is really bad programming, but at least it works.
I won't accept my answer, in case someone find out what was wrong with my update() function and could possibly help someone else (and even me, so that I can improve my code).
That's it :)
Here is the portion of relevant code :
public void onClickStartStop(View v){
//go straight to relevant part
String date_deb = criseCursor.getString(criseCursor.getColumnIndex(CriseContract.COLUMN_NAME_CRISE_DEBUT));
Log.v("andromed", "Need to close the crisis");
cv.put(CriseContract.COLUMN_NAME_CRISE_ID, criseCursor.getInt(criseCursor.getColumnIndex(CriseContract.COLUMN_NAME_CRISE_ID)));
cv.put(CriseContract.COLUMN_NAME_CRISE_DEBUT, date_deb);
cv.put(CriseContract.COLUMN_NAME_CRISE_FIN, d);
int ndel = getContentResolver().delete(CriseContract.CONTENT_URI, CriseContract.COLUMN_NAME_CRISE_ID+"=?", new String[] {""+criseCursor.getInt(criseCursor.getColumnIndex(CriseContract.COLUMN_NAME_CRISE_ID))});
Log.v("andromed", ndel+" rows deleted");
Uri u = getContentResolver().insert(CriseContract.CONTENT_URI, cv);
user_info = "Crise terminée";
//End of relevant code
}
Thanks to those who might have searched anyway.

app not showing data when opend it for the second time

i am looking to make game of questions and answers.i had taken a textview and 4 radio group buttons.and i am fetching data from the external data file from the assets folder.when i installs the app into the emulater it works fine.when i reopens the app in the emulater it is just showing question not showing any text in the radio buttons.here is my code in the data base file
public String makeatext(String My_database_table,int i) {
SQLiteDatabase myDB = getDatabase();
String results = new String();
try {
String firstColumn = "questions";
// final String KEY_ROWID = "id";
// Cursor c = myDB.rawQuery("SELECT questions FROM " +
// My_database_table+ ";",null);
Cursor c = myDB.query(true, My_database_table,
new String[] { firstColumn },null, null, null, null, null,
null);
int iquestion = c.getColumnIndex(firstColumn);
if(c.moveToPosition(i)){
results = c.getString(iquestion)+"\n";
}
//while (c.moveToPosition(1)) {
//String firstName = c.getString(iquestion);
//results =(" "+ firstName + " ");
//}
return results;
} catch (Exception e) {
Log.e("ERROR","ERROR in Make test file :"+e.toString());
e.printStackTrace();
// TODO: handle exception
}
return results;
}
and in the Activity file i am just calling it as
String shoow = myDb.makeatext("question", Qno);
showQuestion.setText(shoow);
and on the top of the oncreate methode i initilized the data base asprivate final DataBaseHelper myDb = new DataBaseHelper(this);
can any one say me why this is happenig.do i need to write the for loop in the activity file also or shall i take a cursor in the activity class .
plz help me out
thanks in advance
for radio buttons the code in the database file is as follows as i have 4 buttons the code for 4 buttons will be as same as this
public String makeExtra1(String My_database_table ,int positions) {
String results = new String();
try {
String secondColumn = "Extra1";
Cursor c = myDataBase.query(true, My_database_table,
new String[] { secondColumn }, null, null, null, null, null,
null);
int iExtra1 = c.getColumnIndex(secondColumn);
if(c.moveToPosition(positions)){
results = results+c.getString(iExtra1)+"\n";
}
return results;
} catch (Exception e) {
Log.e("ERROR","ERROR in Make test file :"+e.toString());
e.printStackTrace();
// TODO: handle exception
}
return results;}
and in the Activity file
String showextra1 = myDb.makeExtra1("question", Qno);
r0.setText(showextra1);
i repeted this thing for 4 times as changing the makeExtra2,3,4 and in the assinged to r1,r2,r3 as above.
You should call Cursor.close() after reading data from it. Better to do it finally{} block.
If you want to raise only one answer per query - fill where param of myDataBase.query().
The unreachable code error is because you are writing finally{} block after return results;
Move this line after the finally{} block, eclipse will not give you any error.
Also do use myDB.close(); in this finally block.

Categories

Resources