use of com.owncloud.android.lib.resources.files.UploadFileRemoteOperation in project android by nextcloud.
the class FileDataStorageManagerIT method testPhotoSearch.
/**
* This test creates an image, does a photo search (now returned image is not yet in file hierarchy), then root
* folder is refreshed and it is verified that the same image file is used in database
*/
@Test
public void testPhotoSearch() throws IOException {
String remotePath = "/imageFile.png";
VirtualFolderType virtualType = VirtualFolderType.GALLERY;
assertEquals(0, sut.getFolderContent(sut.getFileByDecryptedRemotePath("/"), false).size());
assertEquals(1, sut.getAllFiles().size());
File imageFile = getFile("imageFile.png");
assertTrue(new UploadFileRemoteOperation(imageFile.getAbsolutePath(), remotePath, "image/png", String.valueOf(System.currentTimeMillis() / 1000)).execute(client).isSuccess());
assertNull(sut.getFileByDecryptedRemotePath(remotePath));
// search
SearchRemoteOperation searchRemoteOperation = new SearchRemoteOperation("image/%", PHOTO_SEARCH, false, capability);
RemoteOperationResult<List<RemoteFile>> searchResult = searchRemoteOperation.execute(client);
TestCase.assertTrue(searchResult.isSuccess());
TestCase.assertEquals(1, searchResult.getResultData().size());
OCFile ocFile = FileStorageUtils.fillOCFile(searchResult.getResultData().get(0));
sut.saveFile(ocFile);
List<ContentValues> contentValues = new ArrayList<>();
ContentValues cv = new ContentValues();
cv.put(ProviderMeta.ProviderTableMeta.VIRTUAL_TYPE, virtualType.toString());
cv.put(ProviderMeta.ProviderTableMeta.VIRTUAL_OCFILE_ID, ocFile.getFileId());
contentValues.add(cv);
sut.saveVirtuals(contentValues);
assertEquals(remotePath, ocFile.getRemotePath());
assertEquals(0, sut.getFolderContent(sut.getFileByDecryptedRemotePath("/"), false).size());
assertEquals(1, sut.getVirtualFolderContent(virtualType, false).size());
assertEquals(2, sut.getAllFiles().size());
// update root
assertTrue(new RefreshFolderOperation(sut.getFileByDecryptedRemotePath("/"), System.currentTimeMillis() / 1000, false, false, sut, user, targetContext).execute(client).isSuccess());
assertEquals(1, sut.getFolderContent(sut.getFileByDecryptedRemotePath("/"), false).size());
assertEquals(1, sut.getVirtualFolderContent(virtualType, false).size());
assertEquals(2, sut.getAllFiles().size());
assertEquals(sut.getVirtualFolderContent(virtualType, false).get(0), sut.getFolderContent(sut.getFileByDecryptedRemotePath("/"), false).get(0));
}
use of com.owncloud.android.lib.resources.files.UploadFileRemoteOperation in project android by nextcloud.
the class UploadFileOperation method encryptedUpload.
// gson cannot handle sparse arrays easily, therefore use hashmap
@SuppressLint("AndroidLintUseSparseArrays")
private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile parentFile) {
RemoteOperationResult result = null;
File temporalFile = null;
File originalFile = new File(mOriginalStoragePath);
File expectedFile = null;
FileLock fileLock = null;
long size;
boolean metadataExists = false;
String token = null;
ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProvider(getContext().getContentResolver());
String privateKey = arbitraryDataProvider.getValue(getAccount().name, EncryptionUtils.PRIVATE_KEY);
String publicKey = arbitraryDataProvider.getValue(getAccount().name, EncryptionUtils.PUBLIC_KEY);
try {
// check conditions
result = checkConditions(originalFile);
if (result != null) {
return result;
}
/**
*** E2E ****
*/
token = EncryptionUtils.lockFolder(parentFile, client);
// immediately store it
mUpload.setFolderUnlockToken(token);
uploadsStorageManager.updateUpload(mUpload);
// Update metadata
Pair<Boolean, DecryptedFolderMetadata> metadataPair = EncryptionUtils.retrieveMetadata(parentFile, client, privateKey, publicKey);
metadataExists = metadataPair.first;
DecryptedFolderMetadata metadata = metadataPair.second;
/**
** E2E ****
*/
// check name collision
RemoteOperationResult collisionResult = checkNameCollision(client, metadata, parentFile.isEncrypted());
if (collisionResult != null) {
result = collisionResult;
return collisionResult;
}
mFile.setDecryptedRemotePath(parentFile.getDecryptedRemotePath() + originalFile.getName());
String expectedPath = FileStorageUtils.getDefaultSavePathFor(user.getAccountName(), mFile);
expectedFile = new File(expectedPath);
result = copyFile(originalFile, expectedPath);
if (!result.isSuccess()) {
return result;
}
// Get the last modification date of the file from the file system
String lastModifiedTimestamp = Long.toString(originalFile.lastModified() / 1000);
Long creationTimestamp = FileUtil.getCreationTimestamp(originalFile);
/**
*** E2E ****
*/
// Key, always generate new one
byte[] key = EncryptionUtils.generateKey();
// IV, always generate new one
byte[] iv = EncryptionUtils.randomBytes(EncryptionUtils.ivLength);
EncryptionUtils.EncryptedFile encryptedFile = EncryptionUtils.encryptFile(mFile, key, iv);
// new random file name, check if it exists in metadata
String encryptedFileName = UUID.randomUUID().toString().replaceAll("-", "");
while (metadata.getFiles().get(encryptedFileName) != null) {
encryptedFileName = UUID.randomUUID().toString().replaceAll("-", "");
}
File encryptedTempFile = File.createTempFile("encFile", encryptedFileName);
FileOutputStream fileOutputStream = new FileOutputStream(encryptedTempFile);
fileOutputStream.write(encryptedFile.encryptedBytes);
fileOutputStream.close();
/**
*** E2E ****
*/
FileChannel channel = null;
try {
channel = new RandomAccessFile(mFile.getStoragePath(), "rw").getChannel();
fileLock = channel.tryLock();
} catch (FileNotFoundException e) {
// this basically means that the file is on SD card
// try to copy file to temporary dir if it doesn't exist
String temporalPath = FileStorageUtils.getInternalTemporalPath(user.getAccountName(), mContext) + mFile.getRemotePath();
mFile.setStoragePath(temporalPath);
temporalFile = new File(temporalPath);
Files.deleteIfExists(Paths.get(temporalPath));
result = copy(originalFile, temporalFile);
if (result.isSuccess()) {
if (temporalFile.length() == originalFile.length()) {
channel = new RandomAccessFile(temporalFile.getAbsolutePath(), "rw").getChannel();
fileLock = channel.tryLock();
} else {
result = new RemoteOperationResult(ResultCode.LOCK_FAILED);
}
}
}
try {
size = channel.size();
} catch (IOException e1) {
size = new File(mFile.getStoragePath()).length();
}
for (OCUpload ocUpload : uploadsStorageManager.getAllStoredUploads()) {
if (ocUpload.getUploadId() == getOCUploadId()) {
ocUpload.setFileSize(size);
uploadsStorageManager.updateUpload(ocUpload);
break;
}
}
// / perform the upload
if (size > ChunkedFileUploadRemoteOperation.CHUNK_SIZE_MOBILE) {
boolean onWifiConnection = connectivityService.getConnectivity().isWifi();
mUploadOperation = new ChunkedFileUploadRemoteOperation(encryptedTempFile.getAbsolutePath(), mFile.getParentRemotePath() + encryptedFileName, mFile.getMimeType(), mFile.getEtagInConflict(), lastModifiedTimestamp, onWifiConnection, token, creationTimestamp, mDisableRetries);
} else {
mUploadOperation = new UploadFileRemoteOperation(encryptedTempFile.getAbsolutePath(), mFile.getParentRemotePath() + encryptedFileName, mFile.getMimeType(), mFile.getEtagInConflict(), lastModifiedTimestamp, creationTimestamp, token, mDisableRetries);
}
for (OnDatatransferProgressListener mDataTransferListener : mDataTransferListeners) {
mUploadOperation.addDataTransferProgressListener(mDataTransferListener);
}
if (mCancellationRequested.get()) {
throw new OperationCancelledException();
}
result = mUploadOperation.execute(client);
// location in the Nextcloud local folder
if (!result.isSuccess() && result.getHttpCode() == HttpStatus.SC_PRECONDITION_FAILED) {
result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);
}
if (result.isSuccess()) {
mFile.setDecryptedRemotePath(parentFile.getDecryptedRemotePath() + originalFile.getName());
mFile.setRemotePath(parentFile.getRemotePath() + encryptedFileName);
// update metadata
DecryptedFolderMetadata.DecryptedFile decryptedFile = new DecryptedFolderMetadata.DecryptedFile();
DecryptedFolderMetadata.Data data = new DecryptedFolderMetadata.Data();
data.setFilename(mFile.getDecryptedFileName());
data.setMimetype(mFile.getMimeType());
data.setKey(EncryptionUtils.encodeBytesToBase64String(key));
decryptedFile.setEncrypted(data);
decryptedFile.setInitializationVector(EncryptionUtils.encodeBytesToBase64String(iv));
decryptedFile.setAuthenticationTag(encryptedFile.authenticationTag);
metadata.getFiles().put(encryptedFileName, decryptedFile);
EncryptedFolderMetadata encryptedFolderMetadata = EncryptionUtils.encryptFolderMetadata(metadata, privateKey);
String serializedFolderMetadata = EncryptionUtils.serializeJSON(encryptedFolderMetadata);
// upload metadata
EncryptionUtils.uploadMetadata(parentFile, serializedFolderMetadata, token, client, metadataExists);
// unlock
result = EncryptionUtils.unlockFolder(parentFile, client, token);
if (result.isSuccess()) {
token = null;
}
}
} catch (FileNotFoundException e) {
Log_OC.d(TAG, mFile.getStoragePath() + " not exists anymore");
result = new RemoteOperationResult(ResultCode.LOCAL_FILE_NOT_FOUND);
} catch (OverlappingFileLockException e) {
Log_OC.d(TAG, "Overlapping file lock exception");
result = new RemoteOperationResult(ResultCode.LOCK_FAILED);
} catch (Exception e) {
result = new RemoteOperationResult(e);
} finally {
mUploadStarted.set(false);
if (fileLock != null) {
try {
fileLock.release();
} catch (IOException e) {
Log_OC.e(TAG, "Failed to unlock file with path " + mFile.getStoragePath());
}
}
if (temporalFile != null && !originalFile.equals(temporalFile)) {
temporalFile.delete();
}
if (result == null) {
result = new RemoteOperationResult(ResultCode.UNKNOWN_ERROR);
}
logResult(result, mFile.getStoragePath(), mFile.getRemotePath());
}
if (result.isSuccess()) {
handleSuccessfulUpload(temporalFile, expectedFile, originalFile, client);
} else if (result.getCode() == ResultCode.SYNC_CONFLICT) {
getStorageManager().saveConflict(mFile, mFile.getEtagInConflict());
}
// unlock must be done always
if (token != null) {
RemoteOperationResult unlockFolderResult = EncryptionUtils.unlockFolder(parentFile, client, token);
if (!unlockFolderResult.isSuccess()) {
return unlockFolderResult;
}
}
// delete temporal file
if (temporalFile != null && temporalFile.exists() && !temporalFile.delete()) {
Log_OC.e(TAG, "Could not delete temporal file " + temporalFile.getAbsolutePath());
}
return result;
}
use of com.owncloud.android.lib.resources.files.UploadFileRemoteOperation in project android by nextcloud.
the class FileDataStorageManagerIT method testFolderContent.
@Test
public void testFolderContent() throws IOException {
assertEquals(0, sut.getAllFiles().size());
assertTrue(new CreateFolderRemoteOperation("/1/1/", true).execute(client).isSuccess());
assertTrue(new CreateFolderRemoteOperation("/1/2/", true).execute(client).isSuccess());
assertTrue(new UploadFileRemoteOperation(getDummyFile("/chunkedFile.txt").getAbsolutePath(), "/1/1/chunkedFile.txt", "text/plain", String.valueOf(System.currentTimeMillis() / 1000)).execute(client).isSuccess());
assertTrue(new UploadFileRemoteOperation(getDummyFile("/chunkedFile.txt").getAbsolutePath(), "/1/1/chunkedFile2.txt", "text/plain", String.valueOf(System.currentTimeMillis() / 1000)).execute(client).isSuccess());
File imageFile = getFile("imageFile.png");
assertTrue(new UploadFileRemoteOperation(imageFile.getAbsolutePath(), "/1/1/imageFile.png", "image/png", String.valueOf(System.currentTimeMillis() / 1000)).execute(client).isSuccess());
// sync
assertNull(sut.getFileByDecryptedRemotePath("/1/1/"));
assertTrue(new RefreshFolderOperation(sut.getFileByDecryptedRemotePath("/"), System.currentTimeMillis() / 1000, false, false, sut, user, targetContext).execute(client).isSuccess());
assertTrue(new RefreshFolderOperation(sut.getFileByDecryptedRemotePath("/1/"), System.currentTimeMillis() / 1000, false, false, sut, user, targetContext).execute(client).isSuccess());
assertTrue(new RefreshFolderOperation(sut.getFileByDecryptedRemotePath("/1/1/"), System.currentTimeMillis() / 1000, false, false, sut, user, targetContext).execute(client).isSuccess());
assertEquals(3, sut.getFolderContent(sut.getFileByDecryptedRemotePath("/1/1/"), false).size());
}
use of com.owncloud.android.lib.resources.files.UploadFileRemoteOperation in project android by nextcloud.
the class FileDataStorageManagerIT method testGallerySearch.
/**
* This test creates an image and a video, does a gallery search (now returned image and video is not yet in file
* hierarchy), then root folder is refreshed and it is verified that the same image file is used in database
*/
@Test
public void testGallerySearch() throws IOException {
sut = new FileDataStorageManager(user, targetContext.getContentResolver().acquireContentProviderClient(ProviderMeta.ProviderTableMeta.CONTENT_URI));
String imagePath = "/imageFile.png";
VirtualFolderType virtualType = VirtualFolderType.GALLERY;
assertEquals(0, sut.getFolderContent(sut.getFileByDecryptedRemotePath("/"), false).size());
assertEquals(1, sut.getAllFiles().size());
File imageFile = getFile("imageFile.png");
assertTrue(new UploadFileRemoteOperation(imageFile.getAbsolutePath(), imagePath, "image/png", String.valueOf((System.currentTimeMillis() - 10000) / 1000)).execute(client).isSuccess());
// Check that file does not yet exist in local database
assertNull(sut.getFileByDecryptedRemotePath(imagePath));
String videoPath = "/videoFile.mp4";
File videoFile = getFile("videoFile.mp4");
assertTrue(new UploadFileRemoteOperation(videoFile.getAbsolutePath(), videoPath, "video/mpeg", String.valueOf((System.currentTimeMillis() + 10000) / 1000)).execute(client).isSuccess());
// Check that file does not yet exist in local database
assertNull(sut.getFileByDecryptedRemotePath(videoPath));
// search
SearchRemoteOperation searchRemoteOperation = new SearchRemoteOperation("", GALLERY_SEARCH, false, capability);
RemoteOperationResult<List<RemoteFile>> searchResult = searchRemoteOperation.execute(client);
TestCase.assertTrue(searchResult.isSuccess());
TestCase.assertEquals(2, searchResult.getResultData().size());
// newest file must be video path (as sorted by recently modified)
OCFile ocFile = FileStorageUtils.fillOCFile(searchResult.getResultData().get(0));
sut.saveFile(ocFile);
assertEquals(videoPath, ocFile.getRemotePath());
List<ContentValues> contentValues = new ArrayList<>();
ContentValues cv = new ContentValues();
cv.put(ProviderMeta.ProviderTableMeta.VIRTUAL_TYPE, virtualType.toString());
cv.put(ProviderMeta.ProviderTableMeta.VIRTUAL_OCFILE_ID, ocFile.getFileId());
contentValues.add(cv);
// second is image file, as older
OCFile ocFile2 = FileStorageUtils.fillOCFile(searchResult.getResultData().get(1));
sut.saveFile(ocFile2);
assertEquals(imagePath, ocFile2.getRemotePath());
ContentValues cv2 = new ContentValues();
cv2.put(ProviderMeta.ProviderTableMeta.VIRTUAL_TYPE, virtualType.toString());
cv2.put(ProviderMeta.ProviderTableMeta.VIRTUAL_OCFILE_ID, ocFile2.getFileId());
contentValues.add(cv2);
sut.saveVirtuals(contentValues);
assertEquals(0, sut.getFolderContent(sut.getFileByDecryptedRemotePath("/"), false).size());
assertEquals(2, sut.getVirtualFolderContent(virtualType, false).size());
assertEquals(3, sut.getAllFiles().size());
// update root
assertTrue(new RefreshFolderOperation(sut.getFileByDecryptedRemotePath("/"), System.currentTimeMillis() / 1000, false, false, sut, user, targetContext).execute(client).isSuccess());
assertEquals(2, sut.getFolderContent(sut.getFileByDecryptedRemotePath("/"), false).size());
assertEquals(2, sut.getVirtualFolderContent(virtualType, false).size());
assertEquals(3, sut.getAllFiles().size());
assertEquals(sut.getVirtualFolderContent(virtualType, false).get(0), sut.getFolderContent(sut.getFileByDecryptedRemotePath("/"), false).get(0));
}
use of com.owncloud.android.lib.resources.files.UploadFileRemoteOperation in project android by nextcloud.
the class DocumentsStorageProvider method createFile.
private String createFile(Document targetFolder, String displayName, String mimeType) throws FileNotFoundException {
User user = targetFolder.getUser();
// create dummy file
File tempDir = new File(FileStorageUtils.getTemporalPath(user.getAccountName()));
if (!tempDir.exists() && !tempDir.mkdirs()) {
throw new FileNotFoundException("Temp folder could not be created: " + tempDir.getAbsolutePath());
}
File emptyFile = new File(tempDir, displayName);
if (emptyFile.exists() && !emptyFile.delete()) {
throw new FileNotFoundException("Previous file could not be deleted");
}
try {
if (!emptyFile.createNewFile()) {
throw new FileNotFoundException("File could not be created");
}
} catch (IOException e) {
throw getFileNotFoundExceptionWithCause("File could not be created", e);
}
String newFilePath = targetFolder.getRemotePath() + displayName;
// FIXME we need to update the mimeType somewhere else as well
// perform the upload, no need for chunked operation as we have a empty file
OwnCloudClient client = targetFolder.getClient();
RemoteOperationResult result = new UploadFileRemoteOperation(emptyFile.getAbsolutePath(), newFilePath, mimeType, "", String.valueOf(System.currentTimeMillis() / 1000), FileUtil.getCreationTimestamp(emptyFile), false).execute(client);
if (!result.isSuccess()) {
Log_OC.e(TAG, result.toString());
throw new FileNotFoundException("Failed to upload document with path " + newFilePath);
}
Context context = getNonNullContext();
RemoteOperationResult updateParent = new RefreshFolderOperation(targetFolder.getFile(), System.currentTimeMillis(), false, false, true, targetFolder.getStorageManager(), user, context).execute(client);
if (!updateParent.isSuccess()) {
Log_OC.e(TAG, updateParent.toString());
throw new FileNotFoundException("Failed to create document with documentId " + targetFolder.getDocumentId());
}
Document newFile = new Document(targetFolder.getStorageManager(), newFilePath);
context.getContentResolver().notifyChange(toNotifyUri(targetFolder), null, false);
return newFile.getDocumentId();
}
Aggregations