package org.commcare.xml;
import org.commcare.data.xml.TransactionParser;
import org.commcare.models.encryption.ByteEncrypter;
import org.commcare.android.database.app.models.UserKeyRecord;
import org.commcare.utils.Base64;
import org.commcare.utils.Base64DecoderException;
import org.javarosa.xml.util.InvalidStructureException;
import org.javarosa.xml.util.UnfullfilledRequirementsException;
import org.joda.time.format.ISODateTimeFormat;
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
/**
* @author ctsims
*/
public abstract class KeyRecordParser extends TransactionParser<ArrayList<UserKeyRecord>> {
private final String username;
private final String currentpwd;
private final ArrayList<UserKeyRecord> keyRecords;
public KeyRecordParser(KXmlParser parser, String username, String currentpwd) {
super(parser);
this.username = username;
this.currentpwd = currentpwd;
this.keyRecords = new ArrayList<>();
}
@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");
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
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 = ByteEncrypter.wrapByteArrayWithString(theKey, currentpwd);
UserKeyRecord record = new UserKeyRecord(username, UserKeyRecord.generatePwdHash(currentpwd), wrappedKey, valid, expires, uuid, UserKeyRecord.TYPE_NEW);
keyRecords.add(record);
}
commit(keyRecords);
return keyRecords;
}
@Override
protected Date parseDateTime(String dateValue) {
return ISODateTimeFormat.dateTimeNoMillis().parseDateTime(dateValue).toDate();
}
}