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;
}
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;
}
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;
}
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;
}
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;
}
Aggregations