/** * */ package org.commcare.android.db.legacy; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.HashSet; import java.util.Set; import javax.crypto.Cipher; import javax.crypto.CipherOutputStream; import org.commcare.android.crypt.CryptUtil; import org.commcare.android.database.DbUtil; import org.commcare.android.database.EncryptedModel; import org.commcare.android.database.TableBuilder; import org.commcare.android.util.Base64; import org.javarosa.core.services.storage.IMetaData; import org.javarosa.core.services.storage.Persistable; import org.javarosa.core.util.externalizable.Externalizable; import org.javarosa.core.util.externalizable.PrototypeFactory; import android.content.ContentValues; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.util.Pair; /** * @author ctsims * */ public abstract class LegacyDbHelper { protected Context c; private Cipher encrypter; //private Hashtable<String, EncryptedModel> encryptedModels; public LegacyDbHelper(Context c) { this.c = c; } public LegacyDbHelper(Context c, Cipher encrypter) { this.c = c; this.encrypter = encrypter; } public abstract SQLiteDatabase getHandle(); public Pair<String, String[]> createWhere(String[] fieldNames, Object[] values, EncryptedModel em, Persistable p) throws IllegalArgumentException { Set<String> fields = null; if(p instanceof IMetaData) { IMetaData m = (IMetaData)p; String[] thefields = m.getMetaDataFields(); fields = new HashSet<String>(); for(String s : thefields) { fields.add(LegacyTableBuilder.scrubName(s)); } } if(em instanceof IMetaData) { IMetaData m = (IMetaData)em; String[] thefields = m.getMetaDataFields(); fields = new HashSet<String>(); for(String s : thefields) { fields.add(LegacyTableBuilder.scrubName(s)); } } String ret = ""; String[] arguments = new String[fieldNames.length]; for(int i = 0 ; i < fieldNames.length; ++i) { String columnName = LegacyTableBuilder.scrubName(fieldNames[i]); if(fields != null) { if(!fields.contains(columnName)) { throw new IllegalArgumentException("Model does not contain the column " + columnName + "!"); } } ret += columnName + "=?"; if(em != null && em.isEncrypted(fieldNames[i])) { arguments[i] = encrypt(values[i].toString()); } else { arguments[i] = values[i].toString(); } if(i + 1 < fieldNames.length) { ret += " AND "; } } return new Pair<String, String[]>(ret, arguments); } private String encrypt(String string) { byte[] encrypted = CryptUtil.encrypt(string.getBytes(), encrypter); return Base64.encode(encrypted); } public ContentValues getContentValues(Externalizable e) { boolean encrypt = e instanceof EncryptedModel; assert(!(encrypt) || encrypter != null); ByteArrayOutputStream bos = new ByteArrayOutputStream(); OutputStream out = bos; if(encrypt && ((EncryptedModel)e).isBlobEncrypted()) { out = new CipherOutputStream(bos, encrypter); } try { e.writeExternal(new DataOutputStream(out)); out.close(); } catch (IOException e1) { e1.printStackTrace(); throw new RuntimeException("Failed to serialize externalizable for content values"); } byte[] blob = bos.toByteArray(); ContentValues values = new ContentValues(); if(e instanceof IMetaData) { IMetaData m = (IMetaData)e; for(String key : m.getMetaDataFields()) { Object o = m.getMetaData(key); if(o == null ) { continue;} String value = o.toString(); if(encrypt && ((EncryptedModel)e).isEncrypted(key)) { values.put(TableBuilder.scrubName(key), encrypt(value)); } else { values.put(LegacyTableBuilder.scrubName(key), value); } } } values.put(DbUtil.DATA_COL,blob); return values; } public PrototypeFactory getPrototypeFactory() { return DbUtil.getPrototypeFactory(c); } }