Search in sources :

Example 41 with Element

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;
}
Also used : TreeElement(org.javarosa.core.model.instance.TreeElement) AbstractTreeElement(org.javarosa.core.model.instance.AbstractTreeElement) Element(org.kxml2.kdom.Element) ArrayList(java.util.ArrayList)

Example 42 with Element

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;
    }
}
Also used : TreeElement(org.javarosa.core.model.instance.TreeElement) AbstractTreeElement(org.javarosa.core.model.instance.AbstractTreeElement) Element(org.kxml2.kdom.Element) OutputStreamWriter(java.io.OutputStreamWriter)

Example 43 with Element

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;
}
Also used : ArrayList(java.util.ArrayList) IllegalBlockSizeException(javax.crypto.IllegalBlockSizeException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) BadPaddingException(javax.crypto.BadPaddingException) Document(org.kxml2.kdom.Document) FileSystemException(org.opendatakit.briefcase.model.FileSystemException) ParsingException(org.opendatakit.briefcase.model.ParsingException) MessageDigest(java.security.MessageDigest) InvalidAlgorithmParameterException(java.security.InvalidAlgorithmParameterException) FormInstanceMetadata(org.opendatakit.briefcase.util.XmlManipulationUtils.FormInstanceMetadata) NoSuchPaddingException(javax.crypto.NoSuchPaddingException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) IOException(java.io.IOException) InvalidKeyException(java.security.InvalidKeyException) Cipher(javax.crypto.Cipher) CryptoException(org.opendatakit.briefcase.model.CryptoException) File(java.io.File)

Example 44 with Element

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);
}
Also used : TreeElement(org.javarosa.core.model.instance.TreeElement) AbstractTreeElement(org.javarosa.core.model.instance.AbstractTreeElement) Element(org.kxml2.kdom.Element)

Example 45 with Element

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);
            }
        }
    }
}
Also used : TreeElement(org.javarosa.core.model.instance.TreeElement) AbstractTreeElement(org.javarosa.core.model.instance.AbstractTreeElement) Element(org.kxml2.kdom.Element) IFormElement(org.javarosa.core.model.IFormElement) ArrayList(java.util.ArrayList)

Aggregations

Element (org.kxml2.kdom.Element)50 TreeElement (org.javarosa.core.model.instance.TreeElement)25 AbstractTreeElement (org.javarosa.core.model.instance.AbstractTreeElement)23 ArrayList (java.util.ArrayList)21 IOException (java.io.IOException)17 IFormElement (org.javarosa.core.model.IFormElement)17 KXmlParser (org.kxml2.io.KXmlParser)12 XmlPullParserException (org.xmlpull.v1.XmlPullParserException)12 File (java.io.File)8 Test (org.junit.Test)7 ParsingException (org.opendatakit.briefcase.model.ParsingException)7 XmlPullParser (org.xmlpull.v1.XmlPullParser)7 Document (org.kxml2.kdom.Document)6 UnsupportedEncodingException (java.io.UnsupportedEncodingException)4 FileInputStream (java.io.FileInputStream)3 FileNotFoundException (java.io.FileNotFoundException)3 OutputStreamWriter (java.io.OutputStreamWriter)3 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)3 HashMap (java.util.HashMap)3 KXmlSerializer (org.kxml2.io.KXmlSerializer)3