use of org.kxml2.kdom.Document in project collect by opendatakit.
the class WebUtils method getXmlDocument.
/**
* Common method for returning a parsed xml document given a url and the
* http context and client objects involved in the web connection.
*/
public static DocumentFetchResult getXmlDocument(String urlString, HttpContext localContext, HttpClient httpclient) {
URI u;
try {
URL url = new URL(urlString);
u = url.toURI();
} catch (URISyntaxException | MalformedURLException e) {
Timber.i(e, "Error converting URL %s to uri", urlString);
return new DocumentFetchResult(e.getLocalizedMessage() + // + app.getString(R.string.while_accessing) + urlString);
("while accessing") + urlString, 0);
}
if (u.getHost() == null) {
return new DocumentFetchResult("Invalid server URL (no hostname): " + urlString, 0);
}
// if https then enable preemptive basic auth...
if (u.getScheme().equals("https")) {
enablePreemptiveBasicAuth(localContext, u.getHost());
}
// set up request...
HttpGet req = WebUtils.createOpenRosaHttpGet(u);
req.addHeader(WebUtils.ACCEPT_ENCODING_HEADER, WebUtils.GZIP_CONTENT_ENCODING);
HttpResponse response;
try {
response = httpclient.execute(req, localContext);
int statusCode = response.getStatusLine().getStatusCode();
HttpEntity entity = response.getEntity();
if (statusCode != HttpStatus.SC_OK) {
WebUtils.discardEntityBytes(response);
if (statusCode == HttpStatus.SC_UNAUTHORIZED) {
// clear the cookies -- should not be necessary?
Collect.getInstance().getCookieStore().clear();
}
String webError = response.getStatusLine().getReasonPhrase() + " (" + statusCode + ")";
return new DocumentFetchResult(u.toString() + " responded with: " + webError, statusCode);
}
if (entity == null) {
String error = "No entity body returned from: " + u.toString();
Timber.e(error);
return new DocumentFetchResult(error, 0);
}
if (!entity.getContentType().getValue().toLowerCase(Locale.ENGLISH).contains(WebUtils.HTTP_CONTENT_TYPE_TEXT_XML)) {
WebUtils.discardEntityBytes(response);
String error = "ContentType: " + entity.getContentType().getValue() + " returned from: " + u.toString() + " is not text/xml. This is often caused a network proxy. Do you need " + "to login to your network?";
Timber.e(error);
return new DocumentFetchResult(error, 0);
}
// parse response
Document doc = null;
try {
InputStream is = null;
InputStreamReader isr = null;
try {
is = entity.getContent();
Header contentEncoding = entity.getContentEncoding();
if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase(WebUtils.GZIP_CONTENT_ENCODING)) {
is = new GZIPInputStream(is);
}
isr = new InputStreamReader(is, "UTF-8");
doc = new Document();
KXmlParser parser = new KXmlParser();
parser.setInput(isr);
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
doc.parse(parser);
isr.close();
isr = null;
} finally {
if (isr != null) {
try {
// ensure stream is consumed...
final long count = 1024L;
while (isr.skip(count) == count) {
// skipping to the end of the http entity
}
} catch (Exception e) {
// no-op
Timber.e(e);
}
try {
isr.close();
} catch (IOException e) {
// no-op
Timber.e(e, "Error closing input stream reader");
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
Timber.e(e, "Error closing inputstream");
// no-op
}
}
}
} catch (Exception e) {
String error = "Parsing failed with " + e.getMessage() + "while accessing " + u.toString();
Timber.e(error);
return new DocumentFetchResult(error, 0);
}
boolean isOR = false;
Header[] fields = response.getHeaders(WebUtils.OPEN_ROSA_VERSION_HEADER);
if (fields != null && fields.length >= 1) {
isOR = true;
boolean versionMatch = false;
boolean first = true;
StringBuilder b = new StringBuilder();
for (Header h : fields) {
if (WebUtils.OPEN_ROSA_VERSION.equals(h.getValue())) {
versionMatch = true;
break;
}
if (!first) {
b.append("; ");
}
first = false;
b.append(h.getValue());
}
if (!versionMatch) {
Timber.w("%s unrecognized version(s): %s", WebUtils.OPEN_ROSA_VERSION_HEADER, b.toString());
}
}
return new DocumentFetchResult(doc, isOR);
} catch (Exception e) {
String cause;
Throwable c = e;
while (c.getCause() != null) {
c = c.getCause();
}
cause = c.toString();
String error = "Error: " + cause + " while accessing " + u.toString();
Timber.w(error);
return new DocumentFetchResult(error, 0);
}
}
use of org.kxml2.kdom.Document in project javarosa by opendatakit.
the class XFormSerializer method getUtfBytes.
public static byte[] getUtfBytes(Document doc) {
KXmlSerializer serializer = new KXmlSerializer();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
Writer osw = new OutputStreamWriter(bos, "UTF-8");
serializer.setOutput(osw);
doc.write(serializer);
serializer.flush();
return bos.toByteArray();
} catch (Exception e) {
Std.printStack(e);
return null;
}
}
use of org.kxml2.kdom.Document in project javarosa by opendatakit.
the class XFormSerializingVisitor method visit.
/*
* (non-Javadoc)
* @see org.javarosa.core.model.utils.ITreeVisitor#visit(org.javarosa.core.model.DataModelTree)
*/
public void visit(FormInstance tree) {
theXmlDoc = new Document();
// TreeElement root = tree.getRoot();
TreeElement root = tree.resolveReference(rootRef);
// catch that case and just start at the root.
if (root == null) {
root = tree.getRoot();
}
if (root != null) {
theXmlDoc.addChild(Node.ELEMENT, serializeNode(root));
}
Element top = theXmlDoc.getElement(0);
String[] prefixes = tree.getNamespacePrefixes();
for (int i = 0; i < prefixes.length; ++i) {
top.setPrefix(prefixes[i], tree.getNamespaceURI(prefixes[i]));
}
if (tree.schema != null) {
top.setNamespace(tree.schema);
top.setPrefix("", tree.schema);
}
}
use of org.kxml2.kdom.Document in project briefcase by opendatakit.
the class ExportToCsv method processInstance.
private boolean processInstance(File instanceDir) {
File submission = new File(instanceDir, "submission.xml");
if (!submission.exists() || !submission.isFile()) {
EventBus.publish(new ExportProgressEvent("Submission not found for instance directory: " + instanceDir.getPath(), briefcaseLfd));
return false;
}
processedInstances++;
EventBus.publish(new ExportProgressEvent("Processing instance: " + instanceDir.getName(), briefcaseLfd));
EventBus.publish(new ExportProgressPercentageEvent((processedInstances * 100.0) / totalInstances, briefcaseLfd));
// If we are encrypted, be sure the temporary directory
// that will hold the unencrypted files is created.
// If we aren't encrypted, the temporary directory
// is the same as the instance directory.
File unEncryptedDir;
if (briefcaseLfd.isFileEncryptedForm()) {
// create the temp directory that will hold the unencrypted
// files. Do this in the outputDir so that the briefcase storage location
// can be a read-only network mount. issue 676.
Path path;
try {
path = Files.createTempDirectory(Paths.get(outputDir.toURI()), ".temp");
} catch (IOException e) {
String msg = "Unable to create temp directory.";
log.error(msg, e);
EventBus.publish(new ExportProgressEvent(msg + " Cause : " + e.toString(), briefcaseLfd));
return false;
}
unEncryptedDir = path.toFile();
} else {
unEncryptedDir = instanceDir;
}
// parse the xml document (this is the manifest if encrypted)...
Document doc;
boolean isValidated = false;
try {
doc = XmlManipulationUtils.parseXml(submission);
} catch (ParsingException | FileSystemException e) {
log.error("Error parsing submission", e);
EventBus.publish(new ExportProgressEvent(("Error parsing submission " + instanceDir.getName()) + " Cause: " + e.toString(), briefcaseLfd));
return false;
}
String submissionDate = null;
// extract the submissionDate, if present, from the attributes
// of the root element of the submission or submission manifest (if encrypted).
submissionDate = doc.getRootElement().getAttributeValue(null, "submissionDate");
if (submissionDate == null || submissionDate.length() == 0) {
submissionDate = null;
} else {
Date theDate = WebUtils.parseDate(submissionDate);
DateFormat formatter = DateFormat.getDateTimeInstance();
submissionDate = formatter.format(theDate);
// just return true to skip records out of range
if (startDate != null && theDate.before(startDate)) {
log.info("Submission date is before specified, skipping: " + instanceDir.getName());
return true;
}
if (endDate != null && theDate.after(endDate)) {
log.info("Submission date is after specified, skipping: " + instanceDir.getName());
return true;
}
// don't export records without dates if either date is set
if ((startDate != null || endDate != null) && submissionDate == null) {
log.info("No submission date found, skipping: " + instanceDir.getName());
return true;
}
}
// failure.
try {
if (briefcaseLfd.isFileEncryptedForm()) {
// NOTE: this changes the value of 'doc'
try {
FileSystemUtils.DecryptOutcome outcome = FileSystemUtils.decryptAndValidateSubmission(doc, briefcaseLfd.getPrivateKey(), instanceDir, unEncryptedDir);
doc = outcome.submission;
isValidated = outcome.isValidated;
} catch (ParsingException | CryptoException | FileSystemException e) {
// Was unable to parse file or decrypt file or a file system error occurred
// Hence skip this instance
EventBus.publish(new ExportProgressEvent("Error decrypting submission " + instanceDir.getName() + " Cause: " + e.toString() + " skipping....", briefcaseLfd));
log.info("Error decrypting submission " + instanceDir.getName() + " Cause: " + e.toString());
// update total number of files skipped
totalFilesSkipped++;
return true;
}
}
String instanceId = null;
String base64EncryptedFieldKey = null;
// find an instanceId to use...
try {
FormInstanceMetadata sim = XmlManipulationUtils.getFormInstanceMetadata(doc.getRootElement());
instanceId = sim.instanceId;
base64EncryptedFieldKey = sim.base64EncryptedFieldKey;
} catch (ParsingException e) {
log.error("Could not extract metadata from submission", e);
EventBus.publish(new ExportProgressEvent("Could not extract metadata from submission " + submission.getAbsolutePath(), briefcaseLfd));
return false;
}
if (instanceId == null || instanceId.length() == 0) {
// if we have no instanceID, and there isn't any in the file,
// use the checksum as the id.
// NOTE: encrypted submissions always have instanceIDs.
// This is for legacy non-OpenRosa forms.
long checksum;
try {
checksum = FileUtils.checksumCRC32(submission);
} catch (IOException e1) {
String msg = "Failed during computing of crc";
log.error(msg, e1);
EventBus.publish(new ExportProgressEvent(msg + ": " + e1.getMessage(), briefcaseLfd));
return false;
}
instanceId = "crc32:" + Long.toString(checksum);
}
if (terminationFuture.isCancelled()) {
EventBus.publish(new ExportProgressEvent("Aborted", briefcaseLfd));
return false;
}
EncryptionInformation ei = null;
if (base64EncryptedFieldKey != null) {
try {
ei = new EncryptionInformation(base64EncryptedFieldKey, instanceId, briefcaseLfd.getPrivateKey());
} catch (CryptoException e) {
log.error("Error establishing field decryption", e);
EventBus.publish(new ExportProgressEvent("Error establishing field decryption for submission " + instanceDir.getName() + " Cause: " + e.toString(), briefcaseLfd));
return false;
}
}
// emit the csv record...
try {
OutputStreamWriter osw = fileMap.get(briefcaseLfd.getSubmissionElement());
emitString(osw, true, submissionDate);
emitSubmissionCsv(osw, ei, doc.getRootElement(), briefcaseLfd.getSubmissionElement(), briefcaseLfd.getSubmissionElement(), false, instanceId, unEncryptedDir);
emitString(osw, false, instanceId);
if (briefcaseLfd.isFileEncryptedForm()) {
emitString(osw, false, Boolean.toString(isValidated));
if (!isValidated) {
EventBus.publish(new ExportProgressEvent("Decrypted submission " + instanceDir.getName() + " may be missing attachments and could not be validated.", briefcaseLfd));
}
}
osw.append("\n");
return true;
} catch (IOException e) {
String msg = "Failed writing csv";
log.error(msg, e);
EventBus.publish(new ExportProgressEvent(msg + ": " + e.getMessage(), briefcaseLfd));
return false;
}
} finally {
if (briefcaseLfd.isFileEncryptedForm()) {
// destroy the temp directory and its contents...
try {
FileUtils.deleteDirectory(unEncryptedDir);
} catch (IOException e) {
String msg = "Unable to remove decrypted files";
log.error(msg, e);
EventBus.publish(new ExportProgressEvent(msg + ": " + e.getMessage(), briefcaseLfd));
return false;
}
}
}
}
use of org.kxml2.kdom.Document in project briefcase by opendatakit.
the class FileSystemUtils method decryptAndValidateSubmission.
public static DecryptOutcome decryptAndValidateSubmission(Document doc, PrivateKey rsaPrivateKey, File instanceDir, File unEncryptedDir) throws ParsingException, FileSystemException, CryptoException {
Element rootElement = doc.getRootElement();
String base64EncryptedSymmetricKey;
String instanceIdMetadata = null;
List<String> mediaNames = new ArrayList<>();
String encryptedSubmissionFile;
String base64EncryptedElementSignature;
{
Element base64Key = null;
Element base64Signature = null;
Element encryptedXml = null;
for (int i = 0; i < rootElement.getChildCount(); ++i) {
if (rootElement.getType(i) == Node.ELEMENT) {
Element child = rootElement.getElement(i);
String name = child.getName();
if (name.equals("base64EncryptedKey")) {
base64Key = child;
} else if (name.equals("base64EncryptedElementSignature")) {
base64Signature = child;
} else if (name.equals("encryptedXmlFile")) {
encryptedXml = child;
} else if (name.equals("media")) {
Element media = child;
for (int j = 0; j < media.getChildCount(); ++j) {
if (media.getType(j) == Node.ELEMENT) {
Element mediaChild = media.getElement(j);
String mediaFileElementName = mediaChild.getName();
if (mediaFileElementName.equals("file")) {
String mediaName = XFormParser.getXMLText(mediaChild, true);
if (mediaName == null || mediaName.length() == 0) {
mediaNames.add(null);
} else {
mediaNames.add(mediaName);
}
}
}
}
}
}
}
// verify base64Key
if (base64Key == null) {
throw new ParsingException("Missing base64EncryptedKey element in encrypted form.");
}
base64EncryptedSymmetricKey = XFormParser.getXMLText(base64Key, true);
// get instanceID out of OpenRosa meta block
instanceIdMetadata = XmlManipulationUtils.getOpenRosaInstanceId(rootElement);
if (instanceIdMetadata == null) {
throw new ParsingException("Missing instanceID within meta block of encrypted form.");
}
// get submission filename
if (encryptedXml == null) {
throw new ParsingException("Missing encryptedXmlFile element in encrypted form.");
}
encryptedSubmissionFile = XFormParser.getXMLText(encryptedXml, true);
if (base64Signature == null) {
throw new ParsingException("Missing base64EncryptedElementSignature element in encrypted form.");
}
base64EncryptedElementSignature = XFormParser.getXMLText(base64Signature, true);
}
if (instanceIdMetadata == null || base64EncryptedSymmetricKey == null || base64EncryptedElementSignature == null || encryptedSubmissionFile == null) {
throw new ParsingException("Missing one or more required elements of encrypted form.");
}
FormInstanceMetadata fim;
try {
fim = XmlManipulationUtils.getFormInstanceMetadata(rootElement);
} catch (ParsingException e) {
String msg = "Unable to extract form instance metadata from submission manifest";
log.error(msg, e);
throw new ParsingException(msg + ". Cause: " + e.toString());
}
if (!instanceIdMetadata.equals(fim.instanceId)) {
throw new ParsingException("InstanceID within metadata does not match that on top level element.");
}
boolean isValidated = FileSystemUtils.decryptSubmissionFiles(base64EncryptedSymmetricKey, fim, mediaNames, encryptedSubmissionFile, base64EncryptedElementSignature, rsaPrivateKey, instanceDir, unEncryptedDir);
// and change doc to be the decrypted submission document
File decryptedSubmission = new File(unEncryptedDir, "submission.xml");
doc = XmlManipulationUtils.parseXml(decryptedSubmission);
if (doc == null) {
return null;
}
// verify that the metadata matches between the manifest and the submission
rootElement = doc.getRootElement();
FormInstanceMetadata sim = XmlManipulationUtils.getFormInstanceMetadata(rootElement);
if (!fim.xparam.equals(sim.xparam)) {
throw new ParsingException("FormId or version in decrypted submission does not match that in manifest!");
}
if (!fim.instanceId.equals(sim.instanceId)) {
throw new ParsingException("InstanceId in decrypted submission does not match that in manifest!");
}
return new DecryptOutcome(doc, isValidated);
}
Aggregations