Search in sources :

Example 51 with Instance

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;
        }
    });
}
Also used : FormsRepository(org.odk.collect.forms.FormsRepository) Instance(org.odk.collect.forms.instances.Instance) InstancesRepository(org.odk.collect.forms.instances.InstancesRepository) Settings(org.odk.collect.shared.settings.Settings)

Example 52 with Instance

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());
            }
        }
    }
}
Also used : FormController(org.odk.collect.android.javarosawrapper.FormController) EncryptionUtils(org.odk.collect.android.utilities.EncryptionUtils) Instance(org.odk.collect.forms.instances.Instance) LocalizedApplicationKt.getLocalizedString(org.odk.collect.strings.localization.LocalizedApplicationKt.getLocalizedString) File(java.io.File) Uri(android.net.Uri)

Example 53 with Instance

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);
}
Also used : Form(org.odk.collect.forms.Form) Instance(org.odk.collect.forms.instances.Instance) PublicKey(java.security.PublicKey) NoSuchPaddingException(javax.crypto.NoSuchPaddingException) X509EncodedKeySpec(java.security.spec.X509EncodedKeySpec) LocalizedApplicationKt.getLocalizedString(org.odk.collect.strings.localization.LocalizedApplicationKt.getLocalizedString) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) EncryptionException(org.odk.collect.android.exception.EncryptionException) InvalidKeySpecException(java.security.spec.InvalidKeySpecException) NoSuchProviderException(java.security.NoSuchProviderException) KeyFactory(java.security.KeyFactory)

Example 54 with Instance

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;
}
Also used : ContentValues(android.content.ContentValues) Instance(org.odk.collect.forms.instances.Instance) DatabaseObjectMapper.getValuesFromInstance(org.odk.collect.android.database.DatabaseObjectMapper.getValuesFromInstance) InstancesRepository(org.odk.collect.forms.instances.InstancesRepository) DatabaseInstancesRepository(org.odk.collect.android.database.instances.DatabaseInstancesRepository) Cursor(android.database.Cursor)

Example 55 with Instance

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());
}
Also used : Instance(org.odk.collect.forms.instances.Instance) DatabaseObjectMapper.getValuesFromInstance(org.odk.collect.android.database.DatabaseObjectMapper.getValuesFromInstance)

Aggregations

Instance (org.odk.collect.forms.instances.Instance)62 Test (org.junit.Test)28 InstancesRepository (org.odk.collect.forms.instances.InstancesRepository)23 InstancesRepositoryProvider (org.odk.collect.android.utilities.InstancesRepositoryProvider)10 LocalizedApplicationKt.getLocalizedString (org.odk.collect.strings.localization.LocalizedApplicationKt.getLocalizedString)9 File (java.io.File)7 DatabaseObjectMapper.getValuesFromInstance (org.odk.collect.android.database.DatabaseObjectMapper.getValuesFromInstance)7 Uri (android.net.Uri)6 Form (org.odk.collect.forms.Form)6 InstanceUtils.buildInstance (org.odk.collect.formstest.InstanceUtils.buildInstance)6 Pair (android.util.Pair)5 ArrayList (java.util.ArrayList)5 FormsRepositoryProvider (org.odk.collect.android.utilities.FormsRepositoryProvider)5 Date (java.util.Date)4 FormController (org.odk.collect.android.javarosawrapper.FormController)4 MapPoint (org.odk.collect.geo.maps.MapPoint)4 ContentValues (android.content.ContentValues)3 Intent (android.content.Intent)3 Cursor (android.database.Cursor)3 AsyncTask (android.os.AsyncTask)2