use of org.kxml2.kdom.Element in project briefcase by opendatakit.
the class ExportToCsv method findElementList.
private List<Element> findElementList(Element submissionElement, String name) {
List<Element> ecl = new ArrayList<>();
int maxChildren = submissionElement.getChildCount();
for (int i = 0; i < maxChildren; i++) {
if (submissionElement.getType(i) == Node.ELEMENT) {
Element e = submissionElement.getElement(i);
if (name.equals(e.getName())) {
ecl.add(e);
}
}
}
return ecl;
}
use of org.kxml2.kdom.Element in project briefcase by opendatakit.
the class ExportToCsv method emitRepeatingGroupCsv.
private void emitRepeatingGroupCsv(EncryptionInformation ei, List<Element> groupElementList, TreeElement group, String uniqueParentPath, String uniqueGroupPath, File instanceDir) throws IOException {
OutputStreamWriter osw = fileMap.get(group);
int trueOrdinal = 1;
for (Element groupElement : groupElementList) {
String uniqueGroupInstancePath = uniqueGroupPath + "[" + trueOrdinal + "]";
boolean first = true;
first = emitSubmissionCsv(osw, ei, groupElement, group, group, first, uniqueGroupInstancePath, instanceDir);
emitString(osw, first, uniqueParentPath);
emitString(osw, false, uniqueGroupInstancePath);
emitString(osw, false, uniqueGroupPath);
osw.append("\n");
++trueOrdinal;
}
}
use of org.kxml2.kdom.Element in project briefcase by opendatakit.
the class FileSystemUtils method decryptSubmissionFiles.
private static boolean decryptSubmissionFiles(String base64EncryptedSymmetricKey, FormInstanceMetadata fim, List<String> mediaNames, String encryptedSubmissionFile, String base64EncryptedElementSignature, PrivateKey rsaPrivateKey, File instanceDir, File unencryptedDir) throws FileSystemException, CryptoException, ParsingException {
EncryptionInformation ei = new EncryptionInformation(base64EncryptedSymmetricKey, fim.instanceId, rsaPrivateKey);
byte[] elementDigest;
try {
// construct the base64-encoded RSA-encrypted symmetric key
Cipher pkCipher;
pkCipher = Cipher.getInstance(ASYMMETRIC_ALGORITHM);
// extract digest
pkCipher.init(Cipher.DECRYPT_MODE, rsaPrivateKey);
byte[] encryptedElementSignature = Base64.decodeBase64(base64EncryptedElementSignature);
elementDigest = pkCipher.doFinal(encryptedElementSignature);
} catch (NoSuchAlgorithmException | BadPaddingException | IllegalBlockSizeException | InvalidKeyException | NoSuchPaddingException e) {
String msg = "Error decrypting base64EncryptedElementSignature";
log.error(msg, e);
throw new CryptoException(msg + " Cause: " + e.toString());
}
// NOTE: will decrypt only the files in the media list, plus the encryptedSubmissionFile
File[] allFiles = instanceDir.listFiles();
List<File> filesToProcess = new ArrayList<>();
for (File f : allFiles) {
if (mediaNames.contains(f.getName())) {
filesToProcess.add(f);
} else if (encryptedSubmissionFile.equals(f.getName())) {
filesToProcess.add(f);
}
}
// should have all media files plus one submission.xml.enc file
if (filesToProcess.size() != mediaNames.size() + 1) {
// figure out what we're missing...
int lostFileCount = 0;
List<String> missing = new ArrayList<>();
for (String name : mediaNames) {
if (name == null) {
// this was lost due to an pre-ODK Aggregate 1.4.5 mark-as-complete action
++lostFileCount;
continue;
}
File f = new File(instanceDir, name);
if (!filesToProcess.contains(f)) {
missing.add(name);
}
}
StringBuilder b = new StringBuilder();
for (String name : missing) {
b.append(" ").append(name);
}
if (!filesToProcess.contains(new File(instanceDir, encryptedSubmissionFile))) {
b.append(" ").append(encryptedSubmissionFile);
throw new FileSystemException("Error decrypting: " + instanceDir.getName() + " Missing files:" + b.toString());
} else {
// ignore the fact that we don't have the lost files
if (filesToProcess.size() + lostFileCount != mediaNames.size() + 1) {
throw new FileSystemException("Error decrypting: " + instanceDir.getName() + " Missing files:" + b.toString());
}
}
}
// decrypt the media files IN ORDER.
for (String mediaName : mediaNames) {
String displayedName = (mediaName == null) ? "<missing .enc file>" : mediaName;
File f = (mediaName == null) ? null : new File(instanceDir, mediaName);
try {
decryptFile(ei, f, unencryptedDir);
} catch (InvalidKeyException | NoSuchPaddingException | InvalidAlgorithmParameterException | NoSuchAlgorithmException e) {
String msg = "Error decrypting:" + displayedName;
log.error(msg, e);
throw new CryptoException(msg + " Cause: " + e.toString());
} catch (IOException e) {
String msg = "Error decrypting:" + displayedName;
log.error(msg, e);
throw new FileSystemException(msg + " Cause: " + e.toString());
}
}
// decrypt the submission file
File f = new File(instanceDir, encryptedSubmissionFile);
try {
decryptFile(ei, f, unencryptedDir);
} catch (InvalidKeyException | NoSuchPaddingException | InvalidAlgorithmParameterException | NoSuchAlgorithmException e) {
log.error("Error decrypting file", e);
throw new CryptoException("Error decrypting:" + f.getName() + " Cause: " + e.toString());
} catch (IOException e) {
log.error("Error decrypting file", e);
throw new FileSystemException("Error decrypting:" + f.getName() + " Cause: " + e.toString());
}
// get the FIM for the decrypted submission file
File submissionFile = new File(unencryptedDir, encryptedSubmissionFile.substring(0, encryptedSubmissionFile.lastIndexOf(".enc")));
FormInstanceMetadata submissionFim;
try {
Document subDoc = XmlManipulationUtils.parseXml(submissionFile);
submissionFim = XmlManipulationUtils.getFormInstanceMetadata(subDoc.getRootElement());
} catch (ParsingException | FileSystemException e) {
log.error("Error decrypting submission", e);
throw new FileSystemException("Error decrypting: " + submissionFile.getName() + " Cause: " + e);
}
boolean same = submissionFim.xparam.formId.equals(fim.xparam.formId);
if (!same) {
throw new FileSystemException("Error decrypting:" + unencryptedDir.getName() + " Cause: form instance metadata differs from that in manifest");
}
// Construct the element signature string
StringBuilder b = new StringBuilder();
appendElementSignatureSource(b, fim.xparam.formId);
if (fim.xparam.modelVersion != null) {
appendElementSignatureSource(b, fim.xparam.modelVersion);
}
appendElementSignatureSource(b, base64EncryptedSymmetricKey);
appendElementSignatureSource(b, fim.instanceId);
boolean missingFile = false;
for (String encFilename : mediaNames) {
if (encFilename == null) {
missingFile = true;
continue;
}
File decryptedFile = new File(unencryptedDir, encFilename.substring(0, encFilename.lastIndexOf(".enc")));
if (decryptedFile.getName().endsWith(".missing")) {
// this is a missing file -- we will not be able to
// confirm the signature of the submission.
missingFile = true;
continue;
}
String md5 = FileSystemUtils.getMd5Hash(decryptedFile);
appendElementSignatureSource(b, decryptedFile.getName() + "::" + md5);
}
String md5 = FileSystemUtils.getMd5Hash(submissionFile);
appendElementSignatureSource(b, submissionFile.getName() + "::" + md5);
// compute the digest of the element signature string
byte[] messageDigest;
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(b.toString().getBytes("UTF-8"));
messageDigest = md.digest();
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
String msg = "Error computing xml signature";
log.error(msg, e);
throw new CryptoException(msg + " Cause: " + e);
}
same = true;
for (int i = 0; i < messageDigest.length; ++i) {
if (messageDigest[i] != elementDigest[i]) {
same = false;
break;
}
}
return same;
}
use of org.kxml2.kdom.Element in project briefcase by opendatakit.
the class BaseFormParserForJavaRosa method copyBindingElement.
// copy binding and associated attributes to a new binding element (to help
// with maintaining list of original bindings)
private static Element copyBindingElement(Element element) {
Element retval = new Element();
retval.createElement(element.getNamespace(), element.getName());
for (int i = 0; i < element.getAttributeCount(); i++) {
retval.setAttribute(element.getAttributeNamespace(i), element.getAttributeName(i), element.getAttributeValue(i));
}
return (retval);
}
use of org.kxml2.kdom.Element in project javarosa by opendatakit.
the class XFormParser method parseModel.
// for ease of parsing, we assume a model comes before the controls, which isn't necessarily mandated by the xforms spec
private void parseModel(Element e) {
// no attributes parsed in title.
List<String> usedAtts = new ArrayList<>();
List<Element> delayedParseElements = new ArrayList<>();
if (modelFound) {
reporter.warning(XFormParserReporter.TYPE_INVALID_STRUCTURE, "Multiple models not supported. Ignoring subsequent models.", getVagueLocation(e));
return;
}
modelFound = true;
if (XFormUtils.showUnusedAttributeWarning(e, usedAtts)) {
reporter.warning(XFormParserReporter.TYPE_UNKNOWN_MARKUP, XFormUtils.unusedAttWarning(e, usedAtts), getVagueLocation(e));
}
for (int i = 0; i < e.getChildCount(); i++) {
int type = e.getType(i);
Element child = (type == Node.ELEMENT ? e.getElement(i) : null);
String childName = (child != null ? child.getName() : null);
if ("itext".equals(childName)) {
parseIText(child);
} else if ("instance".equals(childName)) {
// we save parsing the instance node until the end, giving us the information we need about
// binds and data types and such
saveInstanceNode(child);
} else if (BIND_ATTR.equals(childName)) {
// <instance> must come before <bind>s
parseBind(child);
} else if ("submission".equals(childName)) {
delayedParseElements.add(child);
} else if (namedActions.contains(childName) || (childName != null && structuredActions.containsKey(childName))) {
delayedParseElements.add(child);
} else {
// invalid model content
if (type == Node.ELEMENT) {
throw new XFormParseException("Unrecognized top-level tag [" + childName + "] found within <model>", child);
} else if (type == Node.TEXT && getXMLText(e, i, true).length() != 0) {
throw new XFormParseException("Unrecognized text content found within <model>: \"" + getXMLText(e, i, true) + "\"", child == null ? e : child);
}
}
if (child == null || BIND_ATTR.equals(childName) || "itext".equals(childName)) {
// Clayton Sims - Jun 17, 2009 - This code is used when the stinginess flag
// is set for the build. It dynamically wipes out old model nodes once they're
// used. This is sketchy if anything else plans on touching the nodes.
// This code can be removed once we're pull-parsing
// #if org.javarosa.xform.stingy
e.removeChild(i);
--i;
// #endif
}
}
// Now parse out the submission/action blocks (we needed the binds to all be set before we could)
for (Element child : delayedParseElements) {
String name = child.getName();
if (name.equals("submission")) {
parseSubmission(child);
} else {
// For now, anything that isn't a submission is an action
if (namedActions.contains(name)) {
parseNamedAction(child);
} else {
structuredActions.get(name).handle(this, child, _f);
}
}
}
}
Aggregations