/*
*
* Panbox - encryption for cloud storage
* Copyright (C) 2014-2015 by Fraunhofer SIT and Sirrix AG
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additonally, third party code may be provided with notices and open source
* licenses from communities and third parties that govern the use of those
* portions, and any licenses granted hereunder do not alter any rights and
* obligations you may have under such open source licenses, however, the
* disclaimer of warranty and limitation of liability provisions of the GPLv3
* will apply to all the product.
*
*/
package org.panbox.mobile.android.identitymgmt;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.LinkedList;
import org.panbox.core.crypto.KeyConstants;
import org.panbox.core.identitymgmt.AbstractAddressbookManager;
import org.panbox.core.identitymgmt.AbstractIdentity;
import org.panbox.core.identitymgmt.AbstractIdentityManager;
import org.panbox.core.identitymgmt.CloudProviderInfo;
import org.panbox.core.identitymgmt.IAddressbook;
import org.panbox.core.identitymgmt.Identity;
import org.panbox.mobile.android.utils.AndroidSettings;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
public class IdentityManagerAndroid extends AbstractIdentityManager {
private static IdentityManagerAndroid idm = null;
// private Context ctx = null;
private static IdentityDBHelper idbh = null;
private SQLiteDatabase db = null;
private IdentityManagerAndroid() {
}
// private IdentityManagerAndroid(Context ctx) {
// this.ctx = ctx;
// }
public static AbstractIdentityManager getInstance(Context ctx) {
if (idm == null) {
idbh = new IdentityDBHelper(ctx);
idm = new IdentityManagerAndroid();
}
return idm;
}
@Override
public void init(AbstractAddressbookManager aBooMgr) {
setAddressBookManager(aBooMgr);
}
@Override
public void storeMyIdentity(AbstractIdentity id) {
// long existingID = identityExists();
long existingID = id.getID();
System.out.println("Store: existing id= " + existingID);
db = idbh.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(AbstractIdentityManager.COLUMN_FirstName, id.getFirstName());
values.put(AbstractIdentityManager.COLUMN_Name, id.getName());
values.put(AbstractIdentityManager.COLUMN_Email, id.getEmail());
values.put(AbstractIdentityManager.COLUMN_KeystorePath, AndroidSettings
.getInstance().getKeystorePath());
if (existingID < 0) {
existingID = db.insert(AbstractIdentityManager.TABLE_IDENTITY,
null, values);
id.setID((int) existingID);
} else {
db.update(AbstractIdentityManager.TABLE_IDENTITY, values, "_id=?",
new String[] { String.valueOf(existingID) });
}
for (CloudProviderInfo cpi : id.getCloudProviders().values()) {
// String q = "select * from "
// + AbstractIdentityManager.TABLE_CLOUDPROVIDER + ", " +
// AbstractIdentityManager.TABLE_CLOUDPROVIDER_MAP
// + " where " + AbstractIdentityManager.TABLE_CLOUDPROVIDER_MAP
// + ".identityID=\"" + existingID + "\" and "
// + AbstractIdentityManager.TABLE_CLOUDPROVIDER_MAP +
// ".cloudProviderID = "
// + AbstractIdentityManager.TABLE_CLOUDPROVIDER +
// "."+AbstractIdentityManager.COLUMN_ID + " and "
// + AbstractIdentityManager.TABLE_CLOUDPROVIDER +
// "."+AbstractIdentityManager.COLUMN_Name + "=\""
// + cpi.getProviderName()+"\"";
//
// Cursor cur = db.rawQuery(q, null);
// cur.moveToFirst();
ContentValues cpiTableVals = new ContentValues();
cpiTableVals.put(AbstractIdentityManager.COLUMN_Username,
cpi.getUsername());
cpiTableVals.put(AbstractIdentityManager.COLUMN_Name,
cpi.getProviderName());
// if (cur.getCount() == 0)
if (cpi.getId() < 0) {
// System.out.println("cpi not found -> adding it: " +
// cpi.getProviderName() + " " + cpi.getUsername());
long insertCpi = db.insert(
AbstractIdentityManager.TABLE_CLOUDPROVIDER, null,
cpiTableVals);
cpi.setId((int) insertCpi);
ContentValues cpiMapTableVals = new ContentValues();
cpiMapTableVals.put(AbstractIdentityManager.COLUMN_IdentityId,
existingID);
cpiMapTableVals.put(
AbstractIdentityManager.COLUMN_CloudproviderId,
insertCpi);
db.insert(AbstractIdentityManager.TABLE_CLOUDPROVIDER_MAP,
null, cpiMapTableVals);
} else {
// long cpiIDinDB = cur.getLong(0);
// System.out.println("cpi found: update ID: " + cpiIDinDB +
// " with values: " + cpi.getProviderName() + " " +
// cpi.getUsername());
db.update(AbstractIdentityManager.TABLE_CLOUDPROVIDER,
cpiTableVals, "_id=?",
new String[] { String.valueOf(cpi.getId()) });
}
// cur.close();
}
// walk through cloud provider infos in db an delete those that are not
// part of the current identity anymore
Cursor cur = db.rawQuery("select * from "
+ AbstractIdentityManager.TABLE_CLOUDPROVIDER + ", "
+ AbstractIdentityManager.TABLE_CLOUDPROVIDER_MAP + " where "
+ AbstractIdentityManager.TABLE_CLOUDPROVIDER_MAP
+ ".identityID=\"" + existingID + "\" and "
+ AbstractIdentityManager.TABLE_CLOUDPROVIDER_MAP
+ ".cloudProviderID = "
+ AbstractIdentityManager.TABLE_CLOUDPROVIDER + "."
+ AbstractIdentityManager.COLUMN_ID, null);
cur.moveToFirst();
LinkedList<Long> toBeRemoved = new LinkedList<Long>();
while (!cur.isAfterLast()) {
long cpiID = cur.getLong(0);
boolean found = false;
for (CloudProviderInfo cpi : id.getCloudProviders().values()) {
if (cpi.getId() == cpiID) {
found = true;
break;
}
}
if (!found) {
toBeRemoved.add(cpiID);
}
cur.moveToNext();
}
cur.close();
for (long cpiID : toBeRemoved) {
db.delete(AbstractIdentityManager.TABLE_CLOUDPROVIDER, "_id=?",
new String[] { String.valueOf(cpiID) });
db.delete(AbstractIdentityManager.TABLE_CLOUDPROVIDER_MAP,
AbstractIdentityManager.COLUMN_CloudproviderId + "=?",
new String[] { String.valueOf(cpiID) });
}
// TODO int vs long on id
getAddressBookManager().persistContacts(id.getAddressbook().getContacts(),
(int) existingID);
// store keystore with private keys in file
File keyStoreFile = new File(AndroidSettings.getInstance().getKeystorePath());
FileOutputStream fos;
try {
fos = new FileOutputStream(keyStoreFile);
Identity idCast = (Identity) id;
idCast.getKeyStore()
.store(fos, KeyConstants.OPEN_KEYSTORE_PASSWORD);
fos.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeyStoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (CertificateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public AbstractIdentity loadMyIdentity(IAddressbook addressbook) {
AndroidSettings pbSettings = AndroidSettings.getInstance();
Identity id = new Identity(addressbook);
db = idbh.getReadableDatabase();
//we use the path in panbox settings now
// String keyStorePath = "";
Cursor cur = db.query(AbstractIdentityManager.TABLE_IDENTITY,
AbstractIdentityManager.ALL_IDENTITY_COLUMNS, null, null, null,
null, null);
long dbID = -1;
cur.moveToFirst();
if(cur.isAfterLast()) {
return null;
}
while (!cur.isAfterLast()) {
dbID = cur.getLong(0);
id.setName(cur.getString(1));
id.setFirstName(cur.getString(2));
id.setEmail(cur.getString(3));
//we use the path in panbox settings now
// keyStorePath = cur.getString(4);
cur.moveToNext();
}
// make sure to close the cursor
cur.close();
// load cloudprovider infos
cur = db.rawQuery("select * from "
+ AbstractIdentityManager.TABLE_CLOUDPROVIDER + ", "
+ AbstractIdentityManager.TABLE_CLOUDPROVIDER_MAP + " where "
+ AbstractIdentityManager.TABLE_CLOUDPROVIDER_MAP
+ ".identityID=\"" + dbID + "\" and "
+ AbstractIdentityManager.TABLE_CLOUDPROVIDER_MAP
+ ".cloudProviderID = "
+ AbstractIdentityManager.TABLE_CLOUDPROVIDER + "."
+ AbstractIdentityManager.COLUMN_ID, null);
cur.moveToFirst();
while (!cur.isAfterLast()) {
CloudProviderInfo cpi = new CloudProviderInfo(cur.getString(2),
cur.getString(1));
cpi.setId((int) cur.getLong(0));
id.addCloudProvider(cpi);
cur.moveToNext();
}
// make sure to close the cursor
cur.close();
id.setID((int) dbID);
// load contacts
getAddressBookManager().loadContacts(id);
// load keystore from file
KeyStore store = null;
try {
store = KeyStore.getInstance(KeyConstants.KEYSTORE_TYPE);
} catch (KeyStoreException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
File keystoreFile = new File(pbSettings.getKeystorePath());
Log.v("IDMA:", "keystoreFile: " + keystoreFile);
if (keystoreFile.exists()) {
FileInputStream fis;
try {
fis = new FileInputStream(keystoreFile);
store.load(fis, KeyConstants.OPEN_KEYSTORE_PASSWORD);
fis.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (CertificateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
id.setKeyStore(store);
} else {
// TODO: error handling
System.err.println("Could not find keystore file");
}
return id;
}
// private long identityExists()
// {
// db = idbh.getReadableDatabase();
//
// Cursor cur = db.query(AbstractIdentityManager.TABLE_IDENTITY,
// AbstractIdentityManager.ALL_IDENTITY_COLUMNS, null, null, null, null,
// null);
//
// if (cur.getCount() == 0)
// {
// return -1;
// }
// else if(cur.getCount() > 1)
// {
// //TODO: error handling
// System.err.println("More than one Identity found -> Database corrupted");
// }
//
// long dbID = -1;
//
// cur.moveToFirst();
// // while (!cur.isAfterLast()) {
// dbID = cur.getLong(0);
//
// // cur.moveToNext();
// // }
// // make sure to close the cursor
// cur.close();
//
// return dbID;
//
// }
}