package org.commcare.xml;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import org.commcare.android.crypt.CryptUtil;
import org.commcare.android.database.app.models.UserKeyRecord;
import org.commcare.android.util.Base64;
import org.commcare.android.util.Base64DecoderException;
import org.commcare.data.xml.TransactionParser;
import org.commcare.xml.util.InvalidStructureException;
import org.commcare.xml.util.UnfullfilledRequirementsException;
import org.joda.time.format.ISODateTimeFormat;
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParserException;
/**
* @author ctsims
*
*/
public abstract class KeyRecordParser extends TransactionParser<ArrayList<UserKeyRecord>> {
String username;
String currentpwd;
ArrayList<UserKeyRecord> keyRecords;
public KeyRecordParser(KXmlParser parser, String username, String currentpwd, ArrayList<UserKeyRecord> keyRecords) {
super(parser,"auth_keys", null);
this.username = username;
this.currentpwd = currentpwd;
this.keyRecords = new ArrayList<UserKeyRecord>();
}
/*
* (non-Javadoc)
* @see org.commcare.xml.ElementParser#parse()
*/
@Override
public ArrayList<UserKeyRecord> parse() throws InvalidStructureException, IOException, XmlPullParserException, UnfullfilledRequirementsException {
this.checkNode("auth_keys");
//TODO: Domain checking and such
while(this.nextTagInBlock("auth_keys")) {
this.checkNode("key_record");
Date valid = getDateAttribute("valid", false);
Date expires = getDateAttribute("expires", true);
this.nextTag("uuid");
String title = parser.getAttributeValue(null, "title");
String uuid = parser.nextText();
if(uuid == null) { throw new InvalidStructureException("No <uuid> value found for incoming key record", parser); }
this.nextTag("key");
//We don't really use this for now
String type = parser.getAttributeValue(null, "type");
//Base64 Encoded AES key
String encodedKey = parser.nextText();
byte[] theKey;
try {
theKey = Base64.decode(encodedKey);
} catch (Base64DecoderException e) {
//Invalid key!
e.printStackTrace();
throw new InvalidStructureException("Invalid AES key in key record", parser);
}
byte[] wrappedKey = CryptUtil.wrapKey(theKey, currentpwd);
UserKeyRecord record = new UserKeyRecord(username, UserKeyRecord.generatePwdHash(currentpwd), wrappedKey, valid, expires, uuid, UserKeyRecord.TYPE_NEW);
keyRecords.add(record);
}
commit(keyRecords);
return keyRecords;
}
protected Date parseDateTime(String dateValue) {
return ISODateTimeFormat.dateTimeNoMillis().parseDateTime(dateValue).toDate();
}
}