Search in sources :

Example 6 with FileSystemException

use of org.opendatakit.briefcase.model.FileSystemException in project briefcase by opendatakit.

the class XmlManipulationUtils method parseXml.

public static Document parseXml(File submission) throws ParsingException, FileSystemException {
    // parse the xml document...
    Document doc = null;
    try {
        InputStream is = null;
        InputStreamReader isr = null;
        try {
            is = new FileInputStream(submission);
            isr = new InputStreamReader(is, UTF_8);
            Document tempDoc = new Document();
            KXmlParser parser = new KXmlParser();
            parser.setInput(isr);
            parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
            tempDoc.parse(parser);
            isr.close();
            doc = tempDoc;
        } finally {
            if (isr != null) {
                try {
                    isr.close();
                } catch (Exception e) {
                // no-op
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (Exception e) {
                // no-op
                }
            }
        }
    } catch (XmlPullParserException e) {
        try {
            return BadXMLFixer.fixBadXML(submission);
        } catch (CannotFixXMLException e1) {
            File debugFileLocation = new File(new StorageLocation().getBriefcaseFolder(), "debug");
            try {
                if (!debugFileLocation.exists()) {
                    FileUtils.forceMkdir(debugFileLocation);
                }
                long checksum = FileUtils.checksumCRC32(submission);
                File debugFile = new File(debugFileLocation, "submission-" + checksum + ".xml");
                FileUtils.copyFile(submission, debugFile);
            } catch (IOException e2) {
                throw new RuntimeException(e2);
            }
            throw new ParsingException("Failed during parsing of submission Xml: " + e.toString());
        }
    } catch (IOException e) {
        throw new FileSystemException("Failed while reading submission xml: " + e.toString());
    }
    return doc;
}
Also used : CannotFixXMLException(org.opendatakit.briefcase.model.CannotFixXMLException) InputStreamReader(java.io.InputStreamReader) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) IOException(java.io.IOException) Document(org.kxml2.kdom.Document) FileInputStream(java.io.FileInputStream) FileSystemException(org.opendatakit.briefcase.model.FileSystemException) CannotFixXMLException(org.opendatakit.briefcase.model.CannotFixXMLException) MalformedURLException(java.net.MalformedURLException) IOException(java.io.IOException) MetadataUpdateException(org.opendatakit.briefcase.model.MetadataUpdateException) FileNotFoundException(java.io.FileNotFoundException) XmlPullParserException(org.xmlpull.v1.XmlPullParserException) ParsingException(org.opendatakit.briefcase.model.ParsingException) KXmlParser(org.kxml2.io.KXmlParser) FileSystemException(org.opendatakit.briefcase.model.FileSystemException) ParsingException(org.opendatakit.briefcase.model.ParsingException) XmlPullParserException(org.xmlpull.v1.XmlPullParserException) StorageLocation(org.opendatakit.briefcase.ui.StorageLocation) MediaFile(org.opendatakit.briefcase.util.ServerFetcher.MediaFile) File(java.io.File)

Example 7 with FileSystemException

use of org.opendatakit.briefcase.model.FileSystemException in project briefcase by opendatakit.

the class ExportToCsv method doAction.

@Override
public boolean doAction() {
    boolean allSuccessful = true;
    File instancesDir;
    try {
        instancesDir = FileSystemUtils.getFormInstancesDirectory(briefcaseLfd.getFormDirectory());
    } catch (FileSystemException e) {
        String msg = "Unable to access instances directory of form";
        log.error(msg, e);
        EventBus.publish(new ExportProgressEvent(msg, briefcaseLfd));
        return false;
    }
    if (!outputDir.exists()) {
        if (!outputDir.mkdir()) {
            EventBus.publish(new ExportProgressEvent("Unable to create destination directory", briefcaseLfd));
            return false;
        }
    }
    if (!processFormDefinition()) {
        // weren't able to initialize the csv file...
        return false;
    }
    File[] instances = instancesDir.listFiles(file -> file.isDirectory() && new File(file, "submission.xml").exists());
    totalInstances = instances.length;
    // assume it to be latest.
    if (instances != null) {
        Arrays.sort(instances, (f1, f2) -> {
            try {
                if (f1.isDirectory() && f2.isDirectory()) {
                    File submission1 = new File(f1, "submission.xml");
                    String submissionDate1String = XmlManipulationUtils.parseXml(submission1).getRootElement().getAttributeValue(null, "submissionDate");
                    File submission2 = new File(f2, "submission.xml");
                    String submissionDate2String = XmlManipulationUtils.parseXml(submission2).getRootElement().getAttributeValue(null, "submissionDate");
                    Date submissionDate1 = StringUtils.isNotEmptyNotNull(submissionDate1String) ? WebUtils.parseDate(submissionDate1String) : new Date();
                    Date submissionDate2 = StringUtils.isNotEmptyNotNull(submissionDate2String) ? WebUtils.parseDate(submissionDate2String) : new Date();
                    return submissionDate1.compareTo(submissionDate2);
                }
            } catch (ParsingException | FileSystemException e) {
                log.error("failed to sort submissions", e);
            }
            return 0;
        });
    }
    for (File instanceDir : instances) {
        if (terminationFuture.isCancelled()) {
            EventBus.publish(new ExportProgressEvent("Aborted", briefcaseLfd));
            allSuccessful = false;
            break;
        }
        if (instanceDir.getName().startsWith("."))
            // Mac OSX
            continue;
        allSuccessful = allSuccessful && processInstance(instanceDir);
    }
    for (OutputStreamWriter w : fileMap.values()) {
        try {
            w.flush();
            w.close();
        } catch (IOException e) {
            String msg = "Error flushing csv file";
            EventBus.publish(new ExportProgressEvent(msg, briefcaseLfd));
            log.error(msg, e);
            allSuccessful = false;
        }
    }
    return allSuccessful;
}
Also used : FileSystemException(org.opendatakit.briefcase.model.FileSystemException) ParsingException(org.opendatakit.briefcase.model.ParsingException) OutputStreamWriter(java.io.OutputStreamWriter) IOException(java.io.IOException) File(java.io.File) ExportProgressEvent(org.opendatakit.briefcase.model.ExportProgressEvent) Date(java.util.Date) LocalDate(java.time.LocalDate)

Example 8 with FileSystemException

use of org.opendatakit.briefcase.model.FileSystemException in project briefcase by opendatakit.

the class FileSystemUtils method assertFormSubmissionDirectory.

public static File assertFormSubmissionDirectory(File formInstancesDir, String instanceID) throws FileSystemException {
    // create instance directory...
    String instanceDirName = asFilesystemSafeName(instanceID);
    File instanceDir = new File(formInstancesDir, instanceDirName);
    if (instanceDir.exists() && instanceDir.isDirectory()) {
        return instanceDir;
    }
    if (!instanceDir.mkdir()) {
        throw new FileSystemException("unable to create instance dir");
    }
    return instanceDir;
}
Also used : FileSystemException(org.opendatakit.briefcase.model.FileSystemException) File(java.io.File)

Example 9 with FileSystemException

use of org.opendatakit.briefcase.model.FileSystemException 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 10 with FileSystemException

use of org.opendatakit.briefcase.model.FileSystemException in project briefcase by opendatakit.

the class TransferFromODK method doResolveOdkCollectFormDefinition.

/**
 * Given the OdkCollectFormDefinition within the FormStatus argument, try to match it up
 * with an existing Briefcase storage form definition, or create a new Briefcase storage
 * form definition for it.
 *
 * @param fs the form transfer status object for an ODK Collect form definition.
 * @return the Briefcase storage form definition.
 */
private BriefcaseFormDefinition doResolveOdkCollectFormDefinition(FormStatus fs) {
    fs.setStatusString("resolving against briefcase form definitions", true);
    EventBus.publish(new FormStatusEvent(fs));
    OdkCollectFormDefinition formDef = (OdkCollectFormDefinition) fs.getFormDefinition();
    File odkFormDefFile = formDef.getFormDefinitionFile();
    BriefcaseFormDefinition briefcaseLfd;
    // copy form definition files from ODK to briefcase (scratch area)
    try {
        briefcaseLfd = BriefcaseFormDefinition.resolveAgainstBriefcaseDefn(odkFormDefFile, true);
        if (briefcaseLfd.needsMediaUpdate()) {
            File destinationFormMediaDir;
            try {
                destinationFormMediaDir = FileSystemUtils.getMediaDirectory(briefcaseLfd.getFormDirectory());
            } catch (FileSystemException e) {
                String msg = "unable to create media folder";
                log.error(msg, e);
                fs.setStatusString(msg + ": " + e.getMessage(), false);
                EventBus.publish(new FormStatusEvent(fs));
                return null;
            }
            // compose the ODK media directory...
            final String odkFormName = odkFormDefFile.getName().substring(0, odkFormDefFile.getName().lastIndexOf("."));
            String odkMediaName = odkFormName + "-media";
            File odkFormMediaDir = new File(odkFormDefFile.getParentFile(), odkMediaName);
            if (odkFormMediaDir.exists()) {
                FileUtils.copyDirectory(odkFormMediaDir, destinationFormMediaDir);
            }
            briefcaseLfd.clearMediaUpdate();
        }
    } catch (Exception e) {
        String msg = "unable to copy form definition and/or media folder";
        log.error(msg, e);
        fs.setStatusString(msg + ": " + e.getMessage(), false);
        EventBus.publish(new FormStatusEvent(fs));
        return null;
    }
    return briefcaseLfd;
}
Also used : FileSystemException(org.opendatakit.briefcase.model.FileSystemException) FormStatusEvent(org.opendatakit.briefcase.model.FormStatusEvent) BriefcaseFormDefinition(org.opendatakit.briefcase.model.BriefcaseFormDefinition) OdkCollectFormDefinition(org.opendatakit.briefcase.model.OdkCollectFormDefinition) File(java.io.File) FileSystemException(org.opendatakit.briefcase.model.FileSystemException) IOException(java.io.IOException) SQLException(java.sql.SQLException) ParsingException(org.opendatakit.briefcase.model.ParsingException)

Aggregations

File (java.io.File)14 FileSystemException (org.opendatakit.briefcase.model.FileSystemException)14 IOException (java.io.IOException)9 ParsingException (org.opendatakit.briefcase.model.ParsingException)7 SQLException (java.sql.SQLException)4 BriefcaseFormDefinition (org.opendatakit.briefcase.model.BriefcaseFormDefinition)4 FormStatusEvent (org.opendatakit.briefcase.model.FormStatusEvent)4 OutputStreamWriter (java.io.OutputStreamWriter)3 Document (org.kxml2.kdom.Document)3 FormStatus (org.opendatakit.briefcase.model.FormStatus)3 LocalDate (java.time.LocalDate)2 Date (java.util.Date)2 CannotFixXMLException (org.opendatakit.briefcase.model.CannotFixXMLException)2 CryptoException (org.opendatakit.briefcase.model.CryptoException)2 ExportProgressEvent (org.opendatakit.briefcase.model.ExportProgressEvent)2 OdkCollectFormDefinition (org.opendatakit.briefcase.model.OdkCollectFormDefinition)2 FileInputStream (java.io.FileInputStream)1 FileNotFoundException (java.io.FileNotFoundException)1 FileOutputStream (java.io.FileOutputStream)1 InputStream (java.io.InputStream)1