Programmatically open password-protected SQLite database with given password - java

I have a password-protected SQLite database. I know the password, and let's say it is 123456qwAS.
I want to embed this password into my app so that my app can open the database automatically. Before this database was password-protected, I had used the following code to open the database:
public void showWordlist()
{
edWord.setEnabled(true);
String word = edWord.getText().toString();
Uri uri = Uri.parse("content://myapp_Provider/dict/" + mDBFile.fileName + "/list/" + word);
edWord.requestFocus();
try
{
#SuppressWarnings("deprecation")
Cursor result = managedQuery(uri,null,null,null,null);
if (result != null)
{
int countRow=result.getCount();
Log.i(MAIN_TAG, "countRow = " + countRow);
mLSTCurrentWord.clear();
//mLSTCurrentContent.clear();
mLSTCurrentWordId.clear();
mAdapter.clear();
if (countRow >= 1)
{
int indexWordColumn = result.getColumnIndex("word");
int indexIdColumn = result.getColumnIndex("id");
result.moveToFirst();
String strWord;
int intId;
int i = 0;
do
{
strWord = Utility.decodeContent(result.getString(indexWordColumn));
intId = result.getInt(indexIdColumn);
mLSTCurrentWord.add(i,strWord);
mLSTCurrentWordId.add(i,intId);
mAdapter.add(strWord);
i++;
} while (result.moveToNext());
}
result.close();
}
lstWord.setAdapter(mAdapter);
}
catch (Exception ex)
{
Log.e(MAIN_TAG, "Error = " + ex.toString());
}
edWord.setEnabled(true);
}
So it comes to my question: How can I programmatically add the above password to this code so that my app can open (and load) the password-protected database automatically?

Android doesn't support encrypted/password-protected SQLite manipulation. As an alternate, you may integrate H2 Database which claims to offer such protection at a cost of almost 1MB overhead.

Related

Why can't my phone app open a file it stored in a Room Database?

Problem: My Android phone app can open various file types stored in an Android Room pre-populated SQLite database but it cannot open files the app itself has added to the pre-populated database (except it can open .txt files). I believe the issue is probably with how the I coded the copying and conversion of a selected file to byte[] data. The app is java based, and I have done this in Java before in a desktop app, so I just can't seem to find the issue. Maybe it is a permission issue, I'm just not sure and someone standing outside looking in may see what I can't.
What I have tried: Since the app can open various existing pre-populated files successfully from the DB, I've concentrated on and stepped through methods writing files to the DB. I'm not receiving any errors. I suspect it may just be minor issue since I can't seem to see it.
What I'm trying to do: I'm trying to emulate the desktop version of this app into a Android phone version. I know it's not recommended or common practice to populate files to a DB, but this app needs to be able to read and write files to the DB supporting it. This will be a full range of file types like the desktop version (e.g., pics, docs, audio, video, etc.). However, as I stated above, .txt files seem to have no issue. The user can select files stored on their phone into a table that captures the fileName and filePath to a TableRow in a TableLayout. Below are methods involved. The plan is to refactor functionality once I get it working:
Capturing the full path and filename for each row - Uses the captured filepath to convert to a byte[] to store the data. The filename and file byte data are stored in a Files table, example, Files(fileName, fileData(byte[])). Each file is added to an ArrayList<Files> which the method returns
public static List<Files> captureNoteFiles(TableLayout table){
List<Files> noteFiles = new ArrayList<>();
int i = table.getChildCount();
if(i>1){
for (int itr = 1; itr<i; itr++) { // iterating through indexes
TableRow tr = (TableRow) table.getChildAt(itr);
TextView tv = (TextView) tr.getChildAt(1); // 1 is the file path position
File f = new File(tv.getText().toString());
String n = f.getName();
try {
FileInputStream fis = new FileInputStream(f.getPath());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
for (int read; (read = fis.read(buf)) != -1; ) {
bos.write(buf, 0, read);
}
fis.close();
noteFiles.add(new Files(0, n, bos.toByteArray()));
} catch (Exception e) {
e.printStackTrace();
Log.d("Input File", e.toString());
}
}
}
return noteFiles;
}
Iteration of the ArrayList - The ArrayList<Files> is iterated and populated to the Files table and an ID capture to associate those files with a particular note of reference.
public static void addNewNoteFiles(int noteID, List<Files> nf){
if(nf.size()>0) {
for (Files f : nf) {
long id = rdb.getFilesDao().addFile(f);
rdb.getFilesByNoteDao().insert(new FilesByNote(noteID, (int) id));
}
}
}
Files Entity
#Entity(tableName = "Files")
public class Files implements Parcelable {
#PrimaryKey(autoGenerate = true)
#ColumnInfo(name = "FileID")
private int fileID;
#ColumnInfo(name = "FileName")
private String fileName;
#TypeConverters(FileTypeConverter.class)
#ColumnInfo(name = "FileData", typeAffinity = ColumnInfo.TEXT)
private byte[] fileData;
#SuppressWarnings(RoomWarnings.CURSOR_MISMATCH)
public Files(int fileID, String fileName, byte[] fileData){
this.fileID = fileID;
this.fileName = fileName;
this.fileData = fileData;
}
}
First you are assuming that an insert works as per :-
long id = rdb.getFilesDao().addFile(f);
rdb.getFilesByNoteDao().insert(new FilesByNote(noteID, (int) id));
What if the row isn't inserted? and returns an id of -1?
So I'd suggest adding getters to the Files class such as :-
public int getFileID() {
return fileID;
}
public String getFileName() {
return fileName;
}
public byte[] getFileData() {
return fileData;
}
and then add the following to FilesDao :-
#Query("SELECT coalesce(length(FileData)) FROM Files WHERE FileID=:fileId")
abstract long getFilesDataLength(long fileId);
and then amending the addNewNoteFiles to be :-
public static void addNewNoteFiles(int noteID, List<Files> nf){
final String TAG = "ADDNEWNOTE";
if(nf.size()>0) {
for (Files f : nf) {
long id = rdb.getFilesDao().addFile(f);
if (id > 0) {
long lengthOfFileData = rdb.getFilesDao().getFilesDataLength(id);
Log.d(TAG,
"Inserted File = " + f.getFileName() +
" DataLength = " + f.getFileData().length +
" ID = " + f.getFileID() +
" Length of Stored Data = " + lengthOfFileData);
if (f.getFileData().length != lengthOfFileData) {
Log.d(TAG,"WARNING FileData length MISMATCH for File = " + f.getFileName() + "\n\t Expected " + f.getFileData().length + " Found " + lengthOfFileData);
}
rdb.getFilesByNoteDao().insert(new FilesByNote(noteID, (int) id));
} else {
Log.d(TAG,"NOT INSERTED File = " + f.getFileName());
}
}
}
}
Run and check the log. Are all the files inserted? Do the lengths match? Are the lengths as expected (if all 0 lengths, or some, then obviously something is amiss when building the ByteArrayOutputStream)
You may wish to add similar for inserting the FilesByNote i.e. have the insert Dao return a long (it returns the rowid) and check if the value is > 0.
You may wonder what rowid is. Well it's a normally hidden column, perhaps hidden as it would appear that FilesByNotes is an associative table mapping(associating) Note(s) with Files and as such has a composite primary key NoteId and FileId which is not an alias of the rowid, so rowid will be hidden as such. However, the value will be auto-generated or -1 if no row is inserted.
ALL tables, with the exception of tables defined with WITHOUT ROWID, have a rowid column. Room does not allow thee definition of WITHOUT ROWID tables.
You wouldn't be concerned about the value if it's greater than 0, just that it is greater than 0 and thus a row was inserted.
The above may help to determine any issues encountered when inserting the data. If there are none found then the issue is else where.

Softlayer - list of servers which are powered on

The following java code lists all the bare metal servers in softlayer for a specific SL account and filters for servers which are powered on (e.g. powerState='on'.
public void listServers(Account.Service service, ApiClient client) throws Exception {
service.withMask().hardware().fullyQualifiedDomainName().primaryIpAddress();
service.withMask().hardware().hardwareStatus();
service.withMask().hardware().id();
Account account = service.getObject();
//
// list of softlayer servers for the client account
//
for (Hardware hardware : account.getHardware()) {
String hostname = hardware.getFullyQualifiedDomainName();
String hardwareStatus = (hardware.getHardwareStatus() == null) ? null : hardware.getHardwareStatus().getStatus();
Long serverId = hardware.getId();
String powerState = null;
if (serverId != null) {
Hardware.Service hardwareService = Hardware.service(client, serverId);
hardwareService.setMask("mask[serverPowerState");
try {
powerState = hardwareService.getServerPowerState();
} catch (Exception ex) {
System.out.println("Error, cannot get powerState, hostname=" + hostname + ", msg=" + ex.getMessage());
}
}
System.out.println("Hostname=" + hostname + ", hwStatus=" + hardwareStatus + ", powerState=" + powerState);
}
}
Code seems to work, but for at least one of the servers, it fails on the call to hardwareService.getServerPowerState()
"Unable to establish IPMI v2 / RMCP+ session".
Any ideas why this is failing ?

NotesException: A required argument has not been provided

My XPage gathers information which I use to populate a document in a different Domino database. I use a link button (so I can open another XPage after submission). The onClick code is as follows:
var rtn = true
var util = new utilities()
var hostURL = configBean.getValue("HostURL");
var userAttachment;
//set up info needed for checking duplicates
var attachName=getComponent("attachmentIdentifier").getValue();
var serialNbr = getComponent("serialNumber").getValue();
userAttachment = user+"~"+attachName;
var userSerial = user+"~"+serialNbr;
//Done setting info needed
//check for duplicates
rtn = utilBean.checkAttachmentName(userAttachment, userSerial)
//done
if(rtn==true){
var doc:Document = document1;
dBar.info("ALL IS GOOD");
var noteID:String=document1.getNoteID();
dBar.info("Calling saveNewAttachment using NoteID " + noteID )
rtn=utilBean.saveNewAttachment(session,noteID ); //<<< I get error here
dBar.info("rtn = " + rtn)
return "xsp-success";
view.postScript("window.open('"+sessionScope.nextURL+"')")
}else if (rtn==false){
errMsgArray = utilBean.getErrorMessages();
for(err in errMsgArray){
//for (i=0; i < errMsgArray.size(); i++){
dBar.info("err: "+ err.toString());
if (err== "nameUsed"){
//send message to XPXage
facesContext.addMessage(attachmentIdentifier.getClientId(facesContext) , msg(langBean.getValue("duplicateName")));
}
if(err=="serialUsed"){
//send message to XPXage
facesContext.addMessage(serialNumber.getClientId(facesContext) , msg(langBean.getValue("duplicateSerial")));
}
}
return "xsp-failure";
}
And the java code that delivers the error is this
public boolean saveNewAttachment(Session ses, String noteID)
throws NotesException {
debugMsg("Entering saveNewAttachment and NOTEID = "+noteID);
// this is used when the user saves an attachment to to the
// user profiles db
boolean rtn = false;
Document doc;
ConfigBean configBean = (ConfigBean)
ExtLibUtil.resolveVariable(FacesContext.getCurrentInstance(),
"configBean");
String dbName = (String) configBean.getValue("WebsiteDbPath");
debugMsg("A");
Database thisDB = ses.getDatabase(ses.getServerName(), dbName, false);
String value;
try {
debugMsg("noteID: "+noteID);
The next line throws the NotesException error
doc = thisDB.getDocumentByID("noteID");
debugMsg("C");
} catch (Exception e) {
debugMsg("utilitiesBean.saveAttachment: " + e.toString());
e.printStackTrace();
System.out.println("utilitiesBean.saveAttachment: " + e.toString());
throw new RuntimeException("utilitiesBean.saveAttachment: "
+ e.toString());
}
return rtn;
}
I might be going about this wrong. I want to save the document which the data is bound to the User Profile database but if I submit it I need to redirect it to a different page. That is why I am using a link, however, I am having a hard time trying to get the document saved.
Has document1 been saved before this code is called? If not, it's not in the backend database to retrieve via getDocumentByID().
I'm assuming this line has been copied into here incorrectly, because "noteID" is not a NoteID or a variable holding a NoteID, it's a string.
doc = thisDB.getDocumentByID("noteID");

Illegal Argument Exception when trying to save an image in Google Drive

When I try to save a captured image into Google Drive, I get the following error:
java.lang.IllegalArgumentException: the name must not be empty: null
at android.accounts.Account.<init>(Account.java:48)
at com.google.android.gms.auth.zzd.getToken(Unknown Source)
at com.google.android.gms.auth.GoogleAuthUtil.getToken(Unknown Source)
at com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential.getToken(GoogleAccountCredential.java:255)
at com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential$RequestHandler.intercept(GoogleAccountCredential.java:279)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:859)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:410)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:343)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:460)
at com.amrutpatil.makeanote.GDActions.search(GDActions.java:290)
at com.amrutpatil.makeanote.GDActions.search(GDActions.java:211)
I can successfully sign in and select a folder on Google Drive, however, when I try to save an image, I get the issue above.
I am currently running Marshmallow on a Nexus 6 physical device.
My GDActions.java code:
private static ArrayList<GF> search(ArrayList<GF> gfs, com.google.api.services.drive.Drive.Files.List qry) throws IOException {
String npTok = null;
if (qry != null) do {
FileList gLst = qry.execute(); //get an error here
if (gLst != null) {
for (File gFl : gLst.getItems()) {
if (gFl.getLabels().getTrashed()) continue;
gfs.add(new GF(gFl.getTitle(), gFl.getId()));
}
npTok = gLst.getNextPageToken();
qry.setPageToken(npTok);
}
} while (npTok != null && npTok.length() > 0);
return gfs;
}
I get an error at FileList gLst = qry.execute() above.
This happens when the search method is invoked here:
static ArrayList<GF> search(String prId, String titl, String mime) {
ArrayList<GF> gfs = new ArrayList<>();
String qryClause = "'me' in owners and ";
if (prId != null) qryClause += "'" + prId + "' in parents and ";
if (titl != null) qryClause += "title = '" + titl + "' and ";
if (mime != null) qryClause += "mimeType = '" + mime + "' and ";
qryClause = qryClause.substring(0, qryClause.length() - " and ".length());
com.google.api.services.drive.Drive.Files.List qry = null;
try {
qry = mGOOSvc.files().list().setQ(qryClause)
.setFields("items(id, labels/trashed, title), nextPageToken");
gfs = search(gfs, qry);
} catch (GoogleAuthIOException gaiEx) {
try {
gfs = search(gfs, qry); //Invoked here
} catch (Exception g) {
GDUT.le(g);
}
} catch (Exception e) {
GDUT.le(e);
}
return gfs;
}
java.lang.IllegalArgumentException: the name must not be empty: null.
The "name" it is referring to is the account name. Ensure that you are setting the GoogleAccountCredential object.
mAccountCredential.setSelectedAccountName("user123#gmail.com");
Note: Set the account name as the full email; user123#gmail.com, instead of just user123.
Turns out that there was a permissions issue. Although I had GET_ACCOUNTS permission set in my AndroidManifest.xml file, I needed to manually enable Contacts permissions in my app settings.
It may be a device specific issue as I was running my app on a Nexus 6 physical device with Android Marshmallow 6.0.1.
You might want to check you app settings just to be safe.

How to implement a Sign in function by using Gigya API in JAVA?

I am trying to delete the accounts from Gigya DB, so we can reuse them to test our login function through Gigya. It seems the UID required for deletion come from login, so how am I suppose to do it in Java?
As mentioned by Ilan, firstly you'll need to include the Gigya Java SDK.
You can then look up the UID using either the Identity Access or Identity Query Tool within Gigya console and use the follow code to delete the account:
// delete user record
GSRequest deleteAccountRequest = new GSRequest(apiKey, secretKey, "accounts.deleteAccount");
//deleteAccountRequest.setAPIDomain("eu1.gigya.com"); // enable this if you're using the EU data centre
deleteAccountRequest.setUseHTTPS(true);
deleteAccountRequest.setParam("UID", uid);
GSResponse deleteAccountResponse = deleteAccountRequest.send();
if(deleteAccountResponse.getErrorCode()==0)
{
}
else
{
System.out.println("deleteAccountResponse failure: " + deleteAccountResponse.getLog());
}
Alternatively, if you want to delete users in batch, you can run a search using accounts.search and delete all the users within the results set:
int limit = 100;
String query = "select UID from accounts where ... " + limit; // add your query here i.e. email = 'someone#example.com'
String cursorId = "";
int objectsCount = limit;
GSRequest searchRequest;
ArrayList<String> uidList = new ArrayList<String>();
// send request
do
{
// check if we have an open cursor
if(cursorId.length() > 0)
{
// run next request in cursor
// set up request
searchRequest = new GSRequest(apiKey, secretKey, "accounts.search");
//searchRequest.setAPIDomain("eu1.gigya.com");
//searchRequest.setUseHTTPS(true);
// set timeout
searchRequest.setParam("timeout", 60000);
// set cursor id
searchRequest.setParam("cursorId", cursorId);
} else {
// run new request and open cursor
// set up request
searchRequest = new GSRequest(apiKey, secretKey, "accounts.search");
//searchRequest.setAPIDomain("eu1.gigya.com");
//searchRequest.setUseHTTPS(true);
// set timeout
searchRequest.setParam("timeout", 60000);
// set query
searchRequest.setParam("query", query);
// open cursor
searchRequest.setParam("openCursor", true);
}
GSResponse searchResponse = searchRequest.send();
if(searchResponse.getErrorCode()==0)
{
GSArray uids = new GSArray();
uids = searchResponse.getArray("results", uids);
for(int i=0; i<uids.length(); i++)
{
String uid;
try {
// retrieve uid and add to list of uids
uid = uids.getObject(i).getString("UID");
uidList.add(uid);
} catch (GSKeyNotFoundException e) {
}
}
cursorId = searchResponse.getString("nextCursorId", "");
objectsCount = searchResponse.getInt("objectsCount", 0);
}
else
{
System.out.println("searchRequest failure: " + searchResponse.getLog());
}
}
while (objectsCount >= limit);
for(int i=0; i<uidList.size(); i++)
{
String uid;
try {
uid = uidList.get(i);
// delete user record
GSRequest deleteAccountRequest = new GSRequest(apiKey, secretKey, "accounts.deleteAccount");
//deleteAccountRequest.setAPIDomain("eu1.gigya.com");
deleteAccountRequest.setUseHTTPS(true);
deleteAccountRequest.setParam("UID", uid);
GSResponse deleteAccountResponse = deleteAccountRequest.send();
if(deleteAccountResponse.getErrorCode()==0)
{
}
else
{
System.out.println("deleteAccountResponse failure: " + deleteAccountResponse.getLog());
}
} catch (Exception e) {
}
}

Categories