use of org.odk.collect.forms.instances.Instance in project collect by opendatakit.
the class InstanceAutoSender method autoSendInstances.
public boolean autoSendInstances(String projectId) {
FormsRepository formsRepository = formsRepositoryProvider.get(projectId);
InstancesRepository instancesRepository = instancesRepositoryProvider.get(projectId);
Settings generalSettings = settingsProvider.getUnprotectedSettings(projectId);
InstanceSubmitter instanceSubmitter = new InstanceSubmitter(analytics, formsRepository, instancesRepository, googleAccountsManager, googleApiProvider, permissionsProvider, generalSettings);
return changeLockProvider.getInstanceLock(projectId).withLock(acquiredLock -> {
if (acquiredLock) {
try {
List<Instance> toUpload = getInstancesToAutoSend(formsRepository, instancesRepository, generalSettings);
Pair<Boolean, String> results = instanceSubmitter.submitInstances(toUpload);
notifier.onSubmission(results.first, results.second, projectId);
} catch (SubmitException e) {
switch(e.getType()) {
case GOOGLE_ACCOUNT_NOT_SET:
notifier.onSubmission(true, context.getString(R.string.google_set_account), projectId);
break;
case GOOGLE_ACCOUNT_NOT_PERMITTED:
notifier.onSubmission(true, context.getString(R.string.odk_permissions_fail), projectId);
break;
case NOTHING_TO_SUBMIT:
break;
}
}
instancesAppState.update();
return true;
} else {
return false;
}
});
}
use of org.odk.collect.forms.instances.Instance in project collect by opendatakit.
the class InstanceDiskSynchronizer method encryptInstance.
private void encryptInstance(Instance instance) throws EncryptionException, IOException {
String instancePath = instance.getInstanceFilePath();
File instanceXml = new File(instancePath);
if (!new File(instanceXml.getParentFile(), "submission.xml.enc").exists()) {
Uri uri = InstancesContract.getUri(currentProjectProvider.getCurrentProject().getUuid(), instance.getDbId());
FormController.InstanceMetadata instanceMetadata = new FormController.InstanceMetadata(getInstanceIdFromInstance(instancePath), null, null);
EncryptionUtils.EncryptedFormInformation formInfo = EncryptionUtils.getEncryptedFormInformation(uri, instanceMetadata);
if (formInfo != null) {
File submissionXml = new File(instanceXml.getParentFile(), "submission.xml");
FileUtils.copyFile(instanceXml, submissionXml);
EncryptionUtils.generateEncryptedSubmission(instanceXml, submissionXml, formInfo);
instancesRepository.save(new Instance.Builder(instance).canEditWhenComplete(false).geometryType(null).geometry(null).build());
SaveFormToDisk.manageFilesAfterSavingEncryptedForm(instanceXml, submissionXml);
if (!EncryptionUtils.deletePlaintextFiles(instanceXml, null)) {
Timber.e("Error deleting plaintext files for %s", instanceXml.getAbsolutePath());
}
}
}
}
use of org.odk.collect.forms.instances.Instance in project collect by opendatakit.
the class EncryptionUtils method getEncryptedFormInformation.
/**
* Retrieve the encryption information for this uri.
*
* @param uri an Instance uri
* @param instanceMetadata the metadata for this instance used to check if the form definition
* defines an instanceID
* @return an {@link EncryptedFormInformation} object if the form definition requests encryption
* and the record can be encrypted. {@code null} if the form definition does not request
* encryption or if the BouncyCastle implementation is not present.
* @throws EncryptionException if the form definition requests encryption but the record can't
* be encrypted
*/
public static EncryptedFormInformation getEncryptedFormInformation(Uri uri, InstanceMetadata instanceMetadata) throws EncryptionException {
// fetch the form information
String formId;
String formVersion;
PublicKey pk;
Form form = null;
if (InstancesContract.CONTENT_ITEM_TYPE.equals(Collect.getInstance().getContentResolver().getType(uri))) {
Instance instance = new InstancesRepositoryProvider(Collect.getInstance()).get().get(ContentUriHelper.getIdFromUri(uri));
if (instance == null) {
String msg = getLocalizedString(Collect.getInstance(), R.string.not_exactly_one_record_for_this_instance);
Timber.e(msg);
throw new EncryptionException(msg, null);
}
formId = instance.getFormId();
formVersion = instance.getFormVersion();
List<Form> forms = new FormsRepositoryProvider(Collect.getInstance()).get().getAllByFormIdAndVersion(formId, formVersion);
// forms with the same formid/version as long as only one is active (not deleted).
if (forms.isEmpty() || new FormsRepositoryProvider(Collect.getInstance()).get().getAllNotDeletedByFormIdAndVersion(formId, formVersion).size() > 1) {
String msg = getLocalizedString(Collect.getInstance(), R.string.not_exactly_one_blank_form_for_this_form_id);
Timber.d(msg);
throw new EncryptionException(msg, null);
}
form = forms.get(0);
} else if (FormsContract.CONTENT_ITEM_TYPE.equals(Collect.getInstance().getContentResolver().getType(uri))) {
throw new IllegalArgumentException("Can't get encryption info for Form URI!");
}
formId = form.getFormId();
if (formId == null || formId.length() == 0) {
String msg = getLocalizedString(Collect.getInstance(), R.string.no_form_id_specified);
Timber.d(msg);
throw new EncryptionException(msg, null);
}
formVersion = form.getVersion();
String base64RsaPublicKey = form.getBASE64RSAPublicKey();
if (base64RsaPublicKey == null) {
// this is legitimately not an encrypted form
return null;
}
byte[] publicKey = Base64.decode(base64RsaPublicKey, Base64.NO_WRAP);
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKey);
KeyFactory kf;
try {
kf = KeyFactory.getInstance(RSA_ALGORITHM);
} catch (NoSuchAlgorithmException e) {
String msg = getLocalizedString(Collect.getInstance(), R.string.phone_does_not_support_rsa);
Timber.d(e, "%s due to %s ", msg, e.getMessage());
throw new EncryptionException(msg, e);
}
try {
pk = kf.generatePublic(publicKeySpec);
} catch (InvalidKeySpecException e) {
String msg = getLocalizedString(Collect.getInstance(), R.string.invalid_rsa_public_key);
Timber.d(e, "%s due to %s ", msg, e.getMessage());
throw new EncryptionException(msg, e);
}
// submission must have an OpenRosa metadata block with a non-null instanceID
if (instanceMetadata.instanceId == null) {
throw new EncryptionException("This form does not specify an instanceID. You must specify one to enable encryption.", null);
}
// https://code.google.com/p/opendatakit/issues/detail?id=918
try {
Cipher.getInstance(EncryptionUtils.SYMMETRIC_ALGORITHM, ENCRYPTION_PROVIDER);
} catch (NoSuchAlgorithmException | NoSuchProviderException | NoSuchPaddingException e) {
String msg;
if (e instanceof NoSuchAlgorithmException) {
msg = "No BouncyCastle implementation of symmetric algorithm!";
} else if (e instanceof NoSuchProviderException) {
msg = "No BouncyCastle provider implementation of symmetric algorithm!";
} else {
msg = "No BouncyCastle provider for padding implementation of symmetric algorithm!";
}
Timber.d(msg);
return null;
}
return new EncryptedFormInformation(formId, formVersion, instanceMetadata, pk);
}
use of org.odk.collect.forms.instances.Instance in project collect by opendatakit.
the class InstanceProvider method update.
@Override
public int update(@NonNull Uri uri, ContentValues values, String where, String[] whereArgs) {
DaggerUtils.getComponent(getContext()).inject(this);
String projectId = getProjectId(uri);
logServerEvent(projectId, AnalyticsEvents.INSTANCE_PROVIDER_UPDATE);
InstancesRepository instancesRepository = instancesRepositoryProvider.get(projectId);
String instancesPath = storagePathProvider.getOdkDirPath(StorageSubdirectory.INSTANCES, projectId);
int count;
switch(URI_MATCHER.match(uri)) {
case INSTANCES:
try (Cursor cursor = dbQuery(projectId, null, where, whereArgs, null)) {
while (cursor.moveToNext()) {
Instance instance = getInstanceFromCurrentCursorPosition(cursor, instancesPath);
ContentValues existingValues = getValuesFromInstance(instance, instancesPath);
existingValues.putAll(values);
instancesRepository.save(getInstanceFromValues(existingValues));
}
count = cursor.getCount();
}
break;
case INSTANCE_ID:
long instanceId = ContentUriHelper.getIdFromUri(uri);
if (whereArgs == null || whereArgs.length == 0) {
Instance instance = instancesRepository.get(instanceId);
ContentValues existingValues = getValuesFromInstance(instance, instancesPath);
existingValues.putAll(values);
instancesRepository.save(getInstanceFromValues(existingValues));
count = 1;
} else {
try (Cursor cursor = dbQuery(projectId, new String[] { _ID }, where, whereArgs, null)) {
while (cursor.moveToNext()) {
if (cursor.getLong(cursor.getColumnIndex(_ID)) == instanceId) {
Instance instance = getInstanceFromCurrentCursorPosition(cursor, instancesPath);
ContentValues existingValues = getValuesFromInstance(instance, instancesPath);
existingValues.putAll(values);
instancesRepository.save(getInstanceFromValues(existingValues));
break;
}
}
}
count = 1;
}
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
use of org.odk.collect.forms.instances.Instance in project collect by opendatakit.
the class InstanceProvider method insert.
@Override
public Uri insert(@NonNull Uri uri, ContentValues initialValues) {
DaggerUtils.getComponent(getContext()).inject(this);
String projectId = getProjectId(uri);
logServerEvent(projectId, AnalyticsEvents.INSTANCE_PROVIDER_INSERT);
// Validate the requested uri
if (URI_MATCHER.match(uri) != INSTANCES) {
throw new IllegalArgumentException("Unknown URI " + uri);
}
Instance newInstance = instancesRepositoryProvider.get(projectId).save(getInstanceFromValues(initialValues));
return getUri(projectId, newInstance.getDbId());
}
Aggregations