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;
}
Related
So I am trying to send data back to my Firebase Database with only users that have signed up and logged in. I have written a code to send the data but i am trying to write an else if statement that a message in this case a Toast appears if they have not signed up. I am struggling to write a code for that.
private void sendScore() {
String userName = name.getText().toString();
String userScore = BenchScore.getText().toString();
if(!TextUtils.isEmpty(userName) && !TextUtils.isEmpty(userScore)) {
String id = databaseReference.push().getKey();
ScoreProfile scoreProfile = new ScoreProfile(id, userName, userScore);
databaseReference.child(FirebaseAuth.getInstance().getUid()).setValue(scoreProfile);
name.setText("");
BenchScore.setText("");
} else if(FirebaseAuth.getInstance().) {
Toast.makeText(Score.this, "You need to sign up in order to use this", Toast.LENGTH_SHORT).show();
}
}
If you want to check if an user is logged in you can use :
...
else if( FirebaseAuth.getInstance().getCurrentUser() == null )
{
// Call your toast here
}
Replace ur code with this one:
private void sendScore() {
String userName = name.getText().toString();
String userScore = BenchScore.getText().toString();
if(FirebaseAuth.getInstance().getUid() != null && !TextUtils.isEmpty(userName) && !TextUtils.isEmpty(userScore)){
String id = databaseReference.push().getKey();
ScoreProfile scoreProfile = new ScoreProfile(id, userName, userScore);
databaseReference.child(FirebaseAuth.getInstance().getUid()).setValue(scoreProfile);
name.setText("");
BenchScore.setText("");
} else if (FirebaseAuth.getInstance().getUid() == null) {
Toast.makeText(Score.this, "You need to sign up in order to use this", Toast.LENGTH_SHORT).show();
}
}
I've just included a check for whether getUid() is non null in the if statement and in else if, I've checked whether getUid() is null. This would serve your purpose, hopefully.
Firebase real time database could not save EditText string or String test_case = "this is test case message" in setValue,but it is successfully saving databaseReference.child(id_key).setValue("given string text");
final Text_Strings text_strings = new Text_Strings(user_name, id_key, title_m, question_m);
// to save elements database referefernce called
databaseReference.child(id_key).setValue(text_strings, new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (databaseError != null) {
Log.d("Data could not be saved ", databaseError.getMessage());
} else {
// it is always saying data
Toast.makeText(getContext(), "Data saved succcessfully ", Toast.LENGTH_SHORT).show();
}
}
});
// to save id_key for test cases
databaseReference.child(id_key).setValue(test_case);
/// to save string elements for test cases
databaseReference.child(id_key).setValue("given string text");
}
});
// return view
return view;
}
}
;
Check whether you are in test mode or applied read write rules correctly .
You can refer to Docs for Read and Write data in Firebase Realtime Database : https://firebase.google.com/docs/database/android/read-and-write
Please paste you complete activity code to better understand your problem.
The android default Email is filter by subject, sender or receiver. But how to filter by content? The message body is not saved to database, which is saved to the file in after Android 5.0. Should I put the message body to the database, which do like before Android 5.0? And then filter the content according the keyword? Please give me some advice, Thanks!
case BODY:
final ContentValues dbValues = new ContentValues(values);
// Prune out the content we don't want in the DB
dbValues.remove(BodyColumns.HTML_CONTENT);
dbValues.remove(BodyColumns.TEXT_CONTENT);
// TODO: move this to the message table
longId = db.insert(Body.TABLE_NAME, "foo", dbValues);
resultUri = ContentUris.withAppendedId(uri, longId);
// Write content to the filesystem where appropriate
// This will look less ugly once the body table is folded into the message table
// and we can just use longId instead
if (!values.containsKey(BodyColumns.MESSAGE_KEY)) {
throw new IllegalArgumentException(
"Cannot insert body without MESSAGE_KEY");
}
final long messageId = values.getAsLong(BodyColumns.MESSAGE_KEY);
// Ensure that no pre-existing body files contaminate the message
deleteBodyFiles(context, messageId);
writeBodyFiles(getContext(), messageId, values);
break;
public static String buildLocalSearchSelection(Context context, long mailboxId,
String queryFilter, String queryFactor) {
StringBuilder selection = new StringBuilder();
selection.append(" (");
queryFilter = queryFilter.replaceAll("\\\\", "\\\\\\\\")
.replaceAll("%", "\\\\%")
.replaceAll("_", "\\\\_")
.replaceAll("'", "''");
String[] queryFilters = queryFilter.split(" +");
boolean isAll = false;
if (queryFactor.contains(SearchParams.SEARCH_FACTOR_ALL)) {
isAll = true;
}
if (queryFactor.contains(SearchParams.SEARCH_FACTOR_SUBJECT) || isAll) {
selection.append(buildSelectionClause(queryFilters, MessageColumns.SUBJECT));
}
if (queryFactor.contains(SearchParams.SEARCH_FACTOR_SENDER) || isAll) {
selection.append(buildSelectionClause(queryFilters, MessageColumns.FROM_LIST));
}
if (queryFactor.contains(SearchParams.SEARCH_FACTOR_RECEIVER) || isAll) {
selection.append(buildSelectionClause(queryFilters, null));
}
selection.delete(selection.length() - " or ".length(), selection.length());
selection.append(")");
return selection.toString();
}
it can use the ' MessageColumns.SNIPPET' to filter the email content.
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
I've got this user class (this is a reduced version for the example, the real one has more parameters but they are implemented the same way):
public class User {
private int _userID;
private String _fullName;
public User(){
}
public User(int userID, String fullName){
this._userID = userID;
this._fullName = fullName;
}
int getUserID(){
return this._userID;
}
String getFullName(){
return this._fullName;
}
void setUserID(int userID){
this._userID = userID;
}
void setFullName(String fullName){
this._fullName = fullName;
}
}
And I want to retrieve a list from my MS SQL Server of this type of objects in Android, I'm using this method inside the connector helper class (the class in charge to make connection to the server using JDBC):
public List<User> getUsers(int ID){
java.sql.ResultSet result = null;
List<User> users = new ArrayList<User>();
User user = new User();
try {
connection = this.getConnection();
if (connection != null) {
//QUERY
String statement = "SELECT * Users WHERE groupID = "
+ ID;
Statement select = connection.createStatement();
//Calls Query
result = select.executeQuery(statement);
while (result.next()){
user.setUserID(result.getInt("UserID"));
user.setFullName(result.getString("FullName"));
System.out.println(result.getString("FullName"));
//Adds to the list
users.add(user);
}
result.close();
result = null;
closeConnection();
}
else {
System.out.println("Error: No active Connection");
}
} catch (Exception e) {
e.printStackTrace();
}
return users;
}
The data is retrieved well from the server according to the System.out.println I'm using in every iteration of the while, the problem is that the list is always filled with repeated information about the last user I retrieve, to clarify:
If I got users A, B and C, when I read user A, list has this structure:[A], when I read user B, list is:[B,B], when I read user C: [C,C,C], etc. So basically all the objects in the list are being overwritten by the last one read.
I've been struggling with this for hours, hope someone can spot the problem because I can't, thanks in advance for the help.
You instantiate a single User object before your loop, and then modify the same User object at each iteration. So you end up with N times the same User object added to your list. You must recreate a new User at each iteration:
while (result.next()){
User user = new User();
user.setUserID(result.getInt("UserID"));
...