Update downloaded files
[pub/Android/ownCloud.git] / src / com / owncloud / android / datamodel / FileDataStorageManager.java
1 /**
2 * ownCloud Android client application
3 *
4 * Copyright (C) 2012 Bartek Przybylski
5 * Copyright (C) 2015 ownCloud Inc.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2,
9 * as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21 package com.owncloud.android.datamodel;
22
23 import java.io.File;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.Iterator;
28 import java.util.List;
29 import java.util.Vector;
30
31 import com.owncloud.android.MainApp;
32 import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
33 import com.owncloud.android.lib.common.utils.Log_OC;
34 import com.owncloud.android.lib.resources.shares.OCShare;
35 import com.owncloud.android.lib.resources.shares.ShareType;
36 import com.owncloud.android.lib.resources.files.FileUtils;
37 import com.owncloud.android.utils.FileStorageUtils;
38
39 import android.accounts.Account;
40 import android.content.ContentProviderClient;
41 import android.content.ContentProviderOperation;
42 import android.content.ContentProviderResult;
43 import android.content.ContentResolver;
44 import android.content.ContentUris;
45 import android.content.ContentValues;
46 import android.content.Intent;
47 import android.content.OperationApplicationException;
48 import android.database.Cursor;
49 import android.net.Uri;
50 import android.os.RemoteException;
51 import android.provider.MediaStore;
52
53 public class FileDataStorageManager {
54
55 public static final int ROOT_PARENT_ID = 0;
56
57 private ContentResolver mContentResolver;
58 private ContentProviderClient mContentProviderClient;
59 private Account mAccount;
60
61 private static String TAG = FileDataStorageManager.class.getSimpleName();
62
63
64 public FileDataStorageManager(Account account, ContentResolver cr) {
65 mContentProviderClient = null;
66 mContentResolver = cr;
67 mAccount = account;
68 }
69
70 public FileDataStorageManager(Account account, ContentProviderClient cp) {
71 mContentProviderClient = cp;
72 mContentResolver = null;
73 mAccount = account;
74 }
75
76
77 public void setAccount(Account account) {
78 mAccount = account;
79 }
80
81 public Account getAccount() {
82 return mAccount;
83 }
84
85 public void setContentResolver(ContentResolver cr) {
86 mContentResolver = cr;
87 }
88
89 public ContentResolver getContentResolver() {
90 return mContentResolver;
91 }
92
93 public void setContentProviderClient(ContentProviderClient cp) {
94 mContentProviderClient = cp;
95 }
96
97 public ContentProviderClient getContentProviderClient() {
98 return mContentProviderClient;
99 }
100
101
102 public OCFile getFileByPath(String path) {
103 Cursor c = getCursorForValue(ProviderTableMeta.FILE_PATH, path);
104 OCFile file = null;
105 if (c.moveToFirst()) {
106 file = createFileInstance(c);
107 }
108 c.close();
109 if (file == null && OCFile.ROOT_PATH.equals(path)) {
110 return createRootDir(); // root should always exist
111 }
112 return file;
113 }
114
115
116 public OCFile getFileById(long id) {
117 Cursor c = getCursorForValue(ProviderTableMeta._ID, String.valueOf(id));
118 OCFile file = null;
119 if (c.moveToFirst()) {
120 file = createFileInstance(c);
121 }
122 c.close();
123 return file;
124 }
125
126 public OCFile getFileByLocalPath(String path) {
127 Cursor c = getCursorForValue(ProviderTableMeta.FILE_STORAGE_PATH, path);
128 OCFile file = null;
129 if (c.moveToFirst()) {
130 file = createFileInstance(c);
131 }
132 c.close();
133 return file;
134 }
135
136 public boolean fileExists(long id) {
137 return fileExists(ProviderTableMeta._ID, String.valueOf(id));
138 }
139
140 public boolean fileExists(String path) {
141 return fileExists(ProviderTableMeta.FILE_PATH, path);
142 }
143
144
145 public Vector<OCFile> getFolderContent(OCFile f) {
146 if (f != null && f.isFolder() && f.getFileId() != -1) {
147 return getFolderContent(f.getFileId());
148
149 } else {
150 return new Vector<OCFile>();
151 }
152 }
153
154
155 public Vector<OCFile> getFolderImages(OCFile folder) {
156 Vector<OCFile> ret = new Vector<OCFile>();
157 if (folder != null) {
158 // TODO better implementation, filtering in the access to database instead of here
159 Vector<OCFile> tmp = getFolderContent(folder);
160 OCFile current = null;
161 for (int i=0; i<tmp.size(); i++) {
162 current = tmp.get(i);
163 if (current.isImage()) {
164 ret.add(current);
165 }
166 }
167 }
168 return ret;
169 }
170
171 public Vector<OCFile> getDownloadedFilesByAccount(String accountName) {
172 Vector<OCFile> ret = new Vector<OCFile>();
173
174 return ret;
175 }
176
177 public boolean saveFile(OCFile file) {
178 boolean overriden = false;
179 ContentValues cv = new ContentValues();
180 cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
181 cv.put(
182 ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
183 file.getModificationTimestampAtLastSyncForData()
184 );
185 cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
186 cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
187 cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
188 cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
189 //if (file.getParentId() != DataStorageManager.ROOT_PARENT_ID)
190 cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
191 cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
192 if (!file.isFolder())
193 cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
194 cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
195 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
196 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
197 cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
198 cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
199 cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
200 cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
201 cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
202 cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
203 cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail());
204 cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading());
205
206 boolean sameRemotePath = fileExists(file.getRemotePath());
207 if (sameRemotePath ||
208 fileExists(file.getFileId()) ) { // for renamed files
209
210 OCFile oldFile = null;
211 if (sameRemotePath) {
212 oldFile = getFileByPath(file.getRemotePath());
213 file.setFileId(oldFile.getFileId());
214 } else {
215 oldFile = getFileById(file.getFileId());
216 }
217
218 overriden = true;
219 if (getContentResolver() != null) {
220 getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv,
221 ProviderTableMeta._ID + "=?",
222 new String[] { String.valueOf(file.getFileId()) });
223 } else {
224 try {
225 getContentProviderClient().update(ProviderTableMeta.CONTENT_URI,
226 cv, ProviderTableMeta._ID + "=?",
227 new String[] { String.valueOf(file.getFileId()) });
228 } catch (RemoteException e) {
229 Log_OC.e(TAG,
230 "Fail to insert insert file to database "
231 + e.getMessage());
232 }
233 }
234 } else {
235 Uri result_uri = null;
236 if (getContentResolver() != null) {
237 result_uri = getContentResolver().insert(
238 ProviderTableMeta.CONTENT_URI_FILE, cv);
239 } else {
240 try {
241 result_uri = getContentProviderClient().insert(
242 ProviderTableMeta.CONTENT_URI_FILE, cv);
243 } catch (RemoteException e) {
244 Log_OC.e(TAG,
245 "Fail to insert insert file to database "
246 + e.getMessage());
247 }
248 }
249 if (result_uri != null) {
250 long new_id = Long.parseLong(result_uri.getPathSegments()
251 .get(1));
252 file.setFileId(new_id);
253 }
254 }
255
256 // if (file.isFolder()) {
257 // updateFolderSize(file.getFileId());
258 // } else {
259 // updateFolderSize(file.getParentId());
260 // }
261
262 return overriden;
263 }
264
265
266 /**
267 * Inserts or updates the list of files contained in a given folder.
268 *
269 * CALLER IS THE RESPONSIBLE FOR GRANTING RIGHT UPDATE OF INFORMATION, NOT THIS METHOD.
270 * HERE ONLY DATA CONSISTENCY SHOULD BE GRANTED
271 *
272 * @param folder
273 * @param updatedFiles
274 * @param filesToRemove
275 */
276 public void saveFolder(
277 OCFile folder, Collection<OCFile> updatedFiles, Collection<OCFile> filesToRemove
278 ) {
279
280 Log_OC.d(TAG, "Saving folder " + folder.getRemotePath() + " with " + updatedFiles.size()
281 + " children and " + filesToRemove.size() + " files to remove");
282
283 ArrayList<ContentProviderOperation> operations =
284 new ArrayList<ContentProviderOperation>(updatedFiles.size());
285
286 // prepare operations to insert or update files to save in the given folder
287 for (OCFile file : updatedFiles) {
288 ContentValues cv = new ContentValues();
289 cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
290 cv.put(
291 ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
292 file.getModificationTimestampAtLastSyncForData()
293 );
294 cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
295 cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
296 cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
297 cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
298 //cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
299 cv.put(ProviderTableMeta.FILE_PARENT, folder.getFileId());
300 cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
301 if (!file.isFolder()) {
302 cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
303 }
304 cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
305 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
306 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
307 cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
308 cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
309 cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
310 cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
311 cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
312 cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
313 cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail());
314 cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading());
315
316 boolean existsByPath = fileExists(file.getRemotePath());
317 if (existsByPath || fileExists(file.getFileId())) {
318 // updating an existing file
319 operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
320 withValues(cv).
321 withSelection( ProviderTableMeta._ID + "=?",
322 new String[] { String.valueOf(file.getFileId()) })
323 .build());
324
325 } else {
326 // adding a new file
327 operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).
328 withValues(cv).build());
329 }
330 }
331
332 // prepare operations to remove files in the given folder
333 String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " +
334 ProviderTableMeta.FILE_PATH + "=?";
335 String [] whereArgs = null;
336 for (OCFile file : filesToRemove) {
337 if (file.getParentId() == folder.getFileId()) {
338 whereArgs = new String[]{mAccount.name, file.getRemotePath()};
339 //Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, "" + file.getFileId());
340 if (file.isFolder()) {
341 operations.add(ContentProviderOperation.newDelete(
342 ContentUris.withAppendedId(
343 ProviderTableMeta.CONTENT_URI_DIR, file.getFileId()
344 )
345 ).withSelection(where, whereArgs).build());
346
347 File localFolder =
348 new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
349 if (localFolder.exists()) {
350 removeLocalFolder(localFolder);
351 }
352 } else {
353 operations.add(ContentProviderOperation.newDelete(
354 ContentUris.withAppendedId(
355 ProviderTableMeta.CONTENT_URI_FILE, file.getFileId()
356 )
357 ).withSelection(where, whereArgs).build());
358
359 if (file.isDown()) {
360 String path = file.getStoragePath();
361 new File(path).delete();
362 triggerMediaScan(path); // notify MediaScanner about removed file
363 }
364 }
365 }
366 }
367
368 // update metadata of folder
369 ContentValues cv = new ContentValues();
370 cv.put(ProviderTableMeta.FILE_MODIFIED, folder.getModificationTimestamp());
371 cv.put(
372 ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
373 folder.getModificationTimestampAtLastSyncForData()
374 );
375 cv.put(ProviderTableMeta.FILE_CREATION, folder.getCreationTimestamp());
376 cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, 0);
377 cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, folder.getMimetype());
378 cv.put(ProviderTableMeta.FILE_NAME, folder.getFileName());
379 cv.put(ProviderTableMeta.FILE_PARENT, folder.getParentId());
380 cv.put(ProviderTableMeta.FILE_PATH, folder.getRemotePath());
381 cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
382 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, folder.getLastSyncDateForProperties());
383 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, folder.getLastSyncDateForData());
384 cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, folder.keepInSync() ? 1 : 0);
385 cv.put(ProviderTableMeta.FILE_ETAG, folder.getEtag());
386 cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, folder.isShareByLink() ? 1 : 0);
387 cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, folder.getPublicLink());
388 cv.put(ProviderTableMeta.FILE_PERMISSIONS, folder.getPermissions());
389 cv.put(ProviderTableMeta.FILE_REMOTE_ID, folder.getRemoteId());
390
391 operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
392 withValues(cv).
393 withSelection( ProviderTableMeta._ID + "=?",
394 new String[] { String.valueOf(folder.getFileId()) })
395 .build());
396
397 // apply operations in batch
398 ContentProviderResult[] results = null;
399 Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
400 try {
401 if (getContentResolver() != null) {
402 results = getContentResolver().applyBatch(MainApp.getAuthority(), operations);
403
404 } else {
405 results = getContentProviderClient().applyBatch(operations);
406 }
407
408 } catch (OperationApplicationException e) {
409 Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
410
411 } catch (RemoteException e) {
412 Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
413 }
414
415 // update new id in file objects for insertions
416 if (results != null) {
417 long newId;
418 Iterator<OCFile> filesIt = updatedFiles.iterator();
419 OCFile file = null;
420 for (int i=0; i<results.length; i++) {
421 if (filesIt.hasNext()) {
422 file = filesIt.next();
423 } else {
424 file = null;
425 }
426 if (results[i].uri != null) {
427 newId = Long.parseLong(results[i].uri.getPathSegments().get(1));
428 //updatedFiles.get(i).setFileId(newId);
429 if (file != null) {
430 file.setFileId(newId);
431 }
432 }
433 }
434 }
435
436 //updateFolderSize(folder.getFileId());
437
438 }
439
440
441 // /**
442 // *
443 // * @param id
444 // */
445 // private void updateFolderSize(long id) {
446 // if (id > FileDataStorageManager.ROOT_PARENT_ID) {
447 // Log_OC.d(TAG, "Updating size of " + id);
448 // if (getContentResolver() != null) {
449 // getContentResolver().update(ProviderTableMeta.CONTENT_URI_DIR,
450 // new ContentValues(),
451 // won't be used, but cannot be null; crashes in KLP
452 // ProviderTableMeta._ID + "=?",
453 // new String[] { String.valueOf(id) });
454 // } else {
455 // try {
456 // getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_DIR,
457 // new ContentValues(),
458 // won't be used, but cannot be null; crashes in KLP
459 // ProviderTableMeta._ID + "=?",
460 // new String[] { String.valueOf(id) });
461 //
462 // } catch (RemoteException e) {
463 // Log_OC.e(
464 // TAG, "Exception in update of folder size through compatibility patch " + e.getMessage());
465 // }
466 // }
467 // } else {
468 // Log_OC.e(TAG, "not updating size for folder " + id);
469 // }
470 // }
471
472
473 public boolean removeFile(OCFile file, boolean removeDBData, boolean removeLocalCopy) {
474 boolean success = true;
475 if (file != null) {
476 if (file.isFolder()) {
477 success = removeFolder(file, removeDBData, removeLocalCopy);
478
479 } else {
480 if (removeDBData) {
481 Uri file_uri = ContentUris.withAppendedId(
482 ProviderTableMeta.CONTENT_URI_FILE,
483 file.getFileId()
484 );
485 String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " +
486 ProviderTableMeta.FILE_PATH + "=?";
487 String [] whereArgs = new String[]{mAccount.name, file.getRemotePath()};
488 int deleted = 0;
489 if (getContentProviderClient() != null) {
490 try {
491 deleted = getContentProviderClient().delete(file_uri, where, whereArgs);
492 } catch (RemoteException e) {
493 e.printStackTrace();
494 }
495 } else {
496 deleted = getContentResolver().delete(file_uri, where, whereArgs);
497 }
498 success &= (deleted > 0);
499 }
500 String localPath = file.getStoragePath();
501 if (removeLocalCopy && file.isDown() && localPath != null && success) {
502 success = new File(localPath).delete();
503 if (success) {
504 deleteFileInMediaScan(localPath);
505 }
506 if (!removeDBData && success) {
507 // maybe unnecessary, but should be checked TODO remove if unnecessary
508 file.setStoragePath(null);
509 saveFile(file);
510 }
511 }
512 }
513 }
514 return success;
515 }
516
517
518 public boolean removeFolder(OCFile folder, boolean removeDBData, boolean removeLocalContent) {
519 boolean success = true;
520 if (folder != null && folder.isFolder()) {
521 if (removeDBData && folder.getFileId() != -1) {
522 success = removeFolderInDb(folder);
523 }
524 if (removeLocalContent && success) {
525 success = removeLocalFolder(folder);
526 }
527 }
528 return success;
529 }
530
531 private boolean removeFolderInDb(OCFile folder) {
532 Uri folder_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, "" +
533 folder.getFileId()); // URI for recursive deletion
534 String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " +
535 ProviderTableMeta.FILE_PATH + "=?";
536 String [] whereArgs = new String[]{mAccount.name, folder.getRemotePath()};
537 int deleted = 0;
538 if (getContentProviderClient() != null) {
539 try {
540 deleted = getContentProviderClient().delete(folder_uri, where, whereArgs);
541 } catch (RemoteException e) {
542 e.printStackTrace();
543 }
544 } else {
545 deleted = getContentResolver().delete(folder_uri, where, whereArgs);
546 }
547 return deleted > 0;
548 }
549
550 private boolean removeLocalFolder(OCFile folder) {
551 boolean success = true;
552 String localFolderPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, folder);
553 File localFolder = new File(localFolderPath);
554 if (localFolder.exists()) {
555 // stage 1: remove the local files already registered in the files database
556 Vector<OCFile> files = getFolderContent(folder.getFileId());
557 if (files != null) {
558 for (OCFile file : files) {
559 if (file.isFolder()) {
560 success &= removeLocalFolder(file);
561 } else {
562 if (file.isDown()) {
563 File localFile = new File(file.getStoragePath());
564 success &= localFile.delete();
565 if (success) {
566 // notify MediaScanner about removed file
567 deleteFileInMediaScan(file.getStoragePath());
568 file.setStoragePath(null);
569 saveFile(file);
570 }
571 }
572 }
573 }
574 }
575
576 // stage 2: remove the folder itself and any local file inside out of sync;
577 // for instance, after clearing the app cache or reinstalling
578 success &= removeLocalFolder(localFolder);
579 }
580 return success;
581 }
582
583 private boolean removeLocalFolder(File localFolder) {
584 boolean success = true;
585 File[] localFiles = localFolder.listFiles();
586 if (localFiles != null) {
587 for (File localFile : localFiles) {
588 if (localFile.isDirectory()) {
589 success &= removeLocalFolder(localFile);
590 } else {
591 String path = localFile.getAbsolutePath();
592 success &= localFile.delete();
593 }
594 }
595 }
596 success &= localFolder.delete();
597 return success;
598 }
599
600
601 /**
602 * Updates database and file system for a file or folder that was moved to a different location.
603 *
604 * TODO explore better (faster) implementations
605 * TODO throw exceptions up !
606 */
607 public void moveLocalFile(OCFile file, String targetPath, String targetParentPath) {
608
609 if (file != null && file.fileExists() && !OCFile.ROOT_PATH.equals(file.getFileName())) {
610
611 OCFile targetParent = getFileByPath(targetParentPath);
612 if (targetParent == null) {
613 throw new IllegalStateException("Parent folder of the target path does not exist!!");
614 }
615
616 /// 1. get all the descendants of the moved element in a single QUERY
617 Cursor c = null;
618 if (getContentProviderClient() != null) {
619 try {
620 c = getContentProviderClient().query(
621 ProviderTableMeta.CONTENT_URI,
622 null,
623 ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " +
624 ProviderTableMeta.FILE_PATH + " LIKE ? ",
625 new String[] {
626 mAccount.name,
627 file.getRemotePath() + "%"
628 },
629 ProviderTableMeta.FILE_PATH + " ASC "
630 );
631 } catch (RemoteException e) {
632 Log_OC.e(TAG, e.getMessage());
633 }
634
635 } else {
636 c = getContentResolver().query(
637 ProviderTableMeta.CONTENT_URI,
638 null,
639 ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " +
640 ProviderTableMeta.FILE_PATH + " LIKE ? ",
641 new String[] {
642 mAccount.name,
643 file.getRemotePath() + "%"
644 },
645 ProviderTableMeta.FILE_PATH + " ASC "
646 );
647 }
648
649 /// 2. prepare a batch of update operations to change all the descendants
650 ArrayList<ContentProviderOperation> operations =
651 new ArrayList<ContentProviderOperation>(c.getCount());
652 String defaultSavePath = FileStorageUtils.getSavePath(mAccount.name);
653 List<String> originalPathsToTriggerMediaScan = new ArrayList<String>();
654 List<String> newPathsToTriggerMediaScan = new ArrayList<String>();
655 if (c.moveToFirst()) {
656 int lengthOfOldPath = file.getRemotePath().length();
657 int lengthOfOldStoragePath = defaultSavePath.length() + lengthOfOldPath;
658 do {
659 ContentValues cv = new ContentValues(); // keep construction in the loop
660 OCFile child = createFileInstance(c);
661 cv.put(
662 ProviderTableMeta.FILE_PATH,
663 targetPath + child.getRemotePath().substring(lengthOfOldPath)
664 );
665 if (child.getStoragePath() != null &&
666 child.getStoragePath().startsWith(defaultSavePath)) {
667 // update link to downloaded content - but local move is not done here!
668 String targetLocalPath = defaultSavePath + targetPath +
669 child.getStoragePath().substring(lengthOfOldStoragePath);
670
671 cv.put(ProviderTableMeta.FILE_STORAGE_PATH, targetLocalPath);
672
673 originalPathsToTriggerMediaScan.add(child.getStoragePath());
674 newPathsToTriggerMediaScan.add(targetLocalPath);
675
676 }
677 if (child.getRemotePath().equals(file.getRemotePath())) {
678 cv.put(
679 ProviderTableMeta.FILE_PARENT,
680 targetParent.getFileId()
681 );
682 }
683 operations.add(
684 ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
685 withValues(cv).
686 withSelection(
687 ProviderTableMeta._ID + "=?",
688 new String[] { String.valueOf(child.getFileId()) }
689 )
690 .build());
691
692 } while (c.moveToNext());
693 }
694 c.close();
695
696 /// 3. apply updates in batch
697 try {
698 if (getContentResolver() != null) {
699 getContentResolver().applyBatch(MainApp.getAuthority(), operations);
700
701 } else {
702 getContentProviderClient().applyBatch(operations);
703 }
704
705 } catch (Exception e) {
706 Log_OC.e(TAG, "Fail to update " + file.getFileId() + " and descendants in database", e);
707 }
708
709 /// 4. move in local file system
710 String originalLocalPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, file);
711 String targetLocalPath = defaultSavePath + targetPath;
712 File localFile = new File(originalLocalPath);
713 boolean renamed = false;
714 if (localFile.exists()) {
715 File targetFile = new File(targetLocalPath);
716 File targetFolder = targetFile.getParentFile();
717 if (!targetFolder.exists()) {
718 targetFolder.mkdirs();
719 }
720 renamed = localFile.renameTo(targetFile);
721 }
722
723 if (renamed) {
724 Iterator<String> it = originalPathsToTriggerMediaScan.iterator();
725 while (it.hasNext()) {
726 // Notify MediaScanner about removed file
727 deleteFileInMediaScan(it.next());
728 }
729 it = newPathsToTriggerMediaScan.iterator();
730 while (it.hasNext()) {
731 // Notify MediaScanner about new file/folder
732 triggerMediaScan(it.next());
733 }
734 }
735 }
736
737 }
738
739
740 private Vector<OCFile> getFolderContent(long parentId) {
741
742 Vector<OCFile> ret = new Vector<OCFile>();
743
744 Uri req_uri = Uri.withAppendedPath(
745 ProviderTableMeta.CONTENT_URI_DIR,
746 String.valueOf(parentId));
747 Cursor c = null;
748
749 if (getContentProviderClient() != null) {
750 try {
751 c = getContentProviderClient().query(req_uri, null,
752 ProviderTableMeta.FILE_PARENT + "=?" ,
753 new String[] { String.valueOf(parentId)}, null);
754 } catch (RemoteException e) {
755 Log_OC.e(TAG, e.getMessage());
756 return ret;
757 }
758 } else {
759 c = getContentResolver().query(req_uri, null,
760 ProviderTableMeta.FILE_PARENT + "=?" ,
761 new String[] { String.valueOf(parentId)}, null);
762 }
763
764 if (c.moveToFirst()) {
765 do {
766 OCFile child = createFileInstance(c);
767 ret.add(child);
768 } while (c.moveToNext());
769 }
770
771 c.close();
772
773 Collections.sort(ret);
774
775 return ret;
776 }
777
778
779 private OCFile createRootDir() {
780 OCFile file = new OCFile(OCFile.ROOT_PATH);
781 file.setMimetype("DIR");
782 file.setParentId(FileDataStorageManager.ROOT_PARENT_ID);
783 saveFile(file);
784 return file;
785 }
786
787 private boolean fileExists(String cmp_key, String value) {
788 Cursor c;
789 if (getContentResolver() != null) {
790 c = getContentResolver()
791 .query(ProviderTableMeta.CONTENT_URI,
792 null,
793 cmp_key + "=? AND "
794 + ProviderTableMeta.FILE_ACCOUNT_OWNER
795 + "=?",
796 new String[] { value, mAccount.name }, null);
797 } else {
798 try {
799 c = getContentProviderClient().query(
800 ProviderTableMeta.CONTENT_URI,
801 null,
802 cmp_key + "=? AND "
803 + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",
804 new String[] { value, mAccount.name }, null);
805 } catch (RemoteException e) {
806 Log_OC.e(TAG,
807 "Couldn't determine file existance, assuming non existance: "
808 + e.getMessage());
809 return false;
810 }
811 }
812 boolean retval = c.moveToFirst();
813 c.close();
814 return retval;
815 }
816
817 private Cursor getCursorForValue(String key, String value) {
818 Cursor c = null;
819 if (getContentResolver() != null) {
820 c = getContentResolver()
821 .query(ProviderTableMeta.CONTENT_URI,
822 null,
823 key + "=? AND "
824 + ProviderTableMeta.FILE_ACCOUNT_OWNER
825 + "=?",
826 new String[] { value, mAccount.name }, null);
827 } else {
828 try {
829 c = getContentProviderClient().query(
830 ProviderTableMeta.CONTENT_URI,
831 null,
832 key + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER
833 + "=?", new String[] { value, mAccount.name },
834 null);
835 } catch (RemoteException e) {
836 Log_OC.e(TAG, "Could not get file details: " + e.getMessage());
837 c = null;
838 }
839 }
840 return c;
841 }
842
843
844 private OCFile createFileInstance(Cursor c) {
845 OCFile file = null;
846 if (c != null) {
847 file = new OCFile(c.getString(c
848 .getColumnIndex(ProviderTableMeta.FILE_PATH)));
849 file.setFileId(c.getLong(c.getColumnIndex(ProviderTableMeta._ID)));
850 file.setParentId(c.getLong(c
851 .getColumnIndex(ProviderTableMeta.FILE_PARENT)));
852 file.setMimetype(c.getString(c
853 .getColumnIndex(ProviderTableMeta.FILE_CONTENT_TYPE)));
854 if (!file.isFolder()) {
855 file.setStoragePath(c.getString(c
856 .getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH)));
857 if (file.getStoragePath() == null) {
858 // try to find existing file and bind it with current account;
859 // with the current update of SynchronizeFolderOperation, this won't be
860 // necessary anymore after a full synchronization of the account
861 File f = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
862 if (f.exists()) {
863 file.setStoragePath(f.getAbsolutePath());
864 file.setLastSyncDateForData(f.lastModified());
865 }
866 }
867 }
868 file.setFileLength(c.getLong(c
869 .getColumnIndex(ProviderTableMeta.FILE_CONTENT_LENGTH)));
870 file.setCreationTimestamp(c.getLong(c
871 .getColumnIndex(ProviderTableMeta.FILE_CREATION)));
872 file.setModificationTimestamp(c.getLong(c
873 .getColumnIndex(ProviderTableMeta.FILE_MODIFIED)));
874 file.setModificationTimestampAtLastSyncForData(c.getLong(c
875 .getColumnIndex(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA)));
876 file.setLastSyncDateForProperties(c.getLong(c
877 .getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE)));
878 file.setLastSyncDateForData(c.getLong(c.
879 getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA)));
880 file.setKeepInSync(c.getInt(
881 c.getColumnIndex(ProviderTableMeta.FILE_KEEP_IN_SYNC)) == 1 ? true : false);
882 file.setEtag(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG)));
883 file.setShareByLink(c.getInt(
884 c.getColumnIndex(ProviderTableMeta.FILE_SHARE_BY_LINK)) == 1 ? true : false);
885 file.setPublicLink(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PUBLIC_LINK)));
886 file.setPermissions(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PERMISSIONS)));
887 file.setRemoteId(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_REMOTE_ID)));
888 file.setNeedsUpdateThumbnail(c.getInt(
889 c.getColumnIndex(ProviderTableMeta.FILE_UPDATE_THUMBNAIL)) == 1 ? true : false);
890 file.setDownloading(c.getInt(
891 c.getColumnIndex(ProviderTableMeta.FILE_IS_DOWNLOADING)) == 1 ? true : false);
892
893 }
894 return file;
895 }
896
897 /**
898 * Returns if the file/folder is shared by link or not
899 * @param path Path of the file/folder
900 * @return
901 */
902 public boolean isShareByLink(String path) {
903 Cursor c = getCursorForValue(ProviderTableMeta.FILE_STORAGE_PATH, path);
904 OCFile file = null;
905 if (c.moveToFirst()) {
906 file = createFileInstance(c);
907 }
908 c.close();
909 return file.isShareByLink();
910 }
911
912 /**
913 * Returns the public link of the file/folder
914 * @param path Path of the file/folder
915 * @return
916 */
917 public String getPublicLink(String path) {
918 Cursor c = getCursorForValue(ProviderTableMeta.FILE_STORAGE_PATH, path);
919 OCFile file = null;
920 if (c.moveToFirst()) {
921 file = createFileInstance(c);
922 }
923 c.close();
924 return file.getPublicLink();
925 }
926
927
928 // Methods for Shares
929 public boolean saveShare(OCShare share) {
930 boolean overriden = false;
931 ContentValues cv = new ContentValues();
932 cv.put(ProviderTableMeta.OCSHARES_FILE_SOURCE, share.getFileSource());
933 cv.put(ProviderTableMeta.OCSHARES_ITEM_SOURCE, share.getItemSource());
934 cv.put(ProviderTableMeta.OCSHARES_SHARE_TYPE, share.getShareType().getValue());
935 cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH, share.getShareWith());
936 cv.put(ProviderTableMeta.OCSHARES_PATH, share.getPath());
937 cv.put(ProviderTableMeta.OCSHARES_PERMISSIONS, share.getPermissions());
938 cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
939 cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
940 cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
941 cv.put(
942 ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME,
943 share.getSharedWithDisplayName()
944 );
945 cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
946 cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
947 cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getIdRemoteShared());
948 cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, mAccount.name);
949
950 if (shareExists(share.getIdRemoteShared())) { // for renamed files
951
952 overriden = true;
953 if (getContentResolver() != null) {
954 getContentResolver().update(ProviderTableMeta.CONTENT_URI_SHARE, cv,
955 ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?",
956 new String[] { String.valueOf(share.getIdRemoteShared()) });
957 } else {
958 try {
959 getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_SHARE,
960 cv, ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?",
961 new String[] { String.valueOf(share.getIdRemoteShared()) });
962 } catch (RemoteException e) {
963 Log_OC.e(TAG,
964 "Fail to insert insert file to database "
965 + e.getMessage());
966 }
967 }
968 } else {
969 Uri result_uri = null;
970 if (getContentResolver() != null) {
971 result_uri = getContentResolver().insert(
972 ProviderTableMeta.CONTENT_URI_SHARE, cv);
973 } else {
974 try {
975 result_uri = getContentProviderClient().insert(
976 ProviderTableMeta.CONTENT_URI_SHARE, cv);
977 } catch (RemoteException e) {
978 Log_OC.e(TAG,
979 "Fail to insert insert file to database "
980 + e.getMessage());
981 }
982 }
983 if (result_uri != null) {
984 long new_id = Long.parseLong(result_uri.getPathSegments()
985 .get(1));
986 share.setId(new_id);
987 }
988 }
989
990 return overriden;
991 }
992
993
994 public OCShare getFirstShareByPathAndType(String path, ShareType type) {
995 Cursor c = null;
996 if (getContentResolver() != null) {
997 c = getContentResolver().query(
998 ProviderTableMeta.CONTENT_URI_SHARE,
999 null,
1000 ProviderTableMeta.OCSHARES_PATH + "=? AND "
1001 + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? AND "
1002 + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?",
1003 new String[] { path, Integer.toString(type.getValue()), mAccount.name },
1004 null);
1005 } else {
1006 try {
1007 c = getContentProviderClient().query(
1008 ProviderTableMeta.CONTENT_URI_SHARE,
1009 null,
1010 ProviderTableMeta.OCSHARES_PATH + "=? AND "
1011 + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? AND "
1012 + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?",
1013 new String[] { path, Integer.toString(type.getValue()), mAccount.name },
1014 null);
1015
1016 } catch (RemoteException e) {
1017 Log_OC.e(TAG, "Could not get file details: " + e.getMessage());
1018 c = null;
1019 }
1020 }
1021 OCShare share = null;
1022 if (c.moveToFirst()) {
1023 share = createShareInstance(c);
1024 }
1025 c.close();
1026 return share;
1027 }
1028
1029 private OCShare createShareInstance(Cursor c) {
1030 OCShare share = null;
1031 if (c != null) {
1032 share = new OCShare(c.getString(c
1033 .getColumnIndex(ProviderTableMeta.OCSHARES_PATH)));
1034 share.setId(c.getLong(c.getColumnIndex(ProviderTableMeta._ID)));
1035 share.setFileSource(c.getLong(c
1036 .getColumnIndex(ProviderTableMeta.OCSHARES_ITEM_SOURCE)));
1037 share.setShareType(ShareType.fromValue(c.getInt(c
1038 .getColumnIndex(ProviderTableMeta.OCSHARES_SHARE_TYPE))));
1039 share.setPermissions(c.getInt(c
1040 .getColumnIndex(ProviderTableMeta.OCSHARES_PERMISSIONS)));
1041 share.setSharedDate(c.getLong(c
1042 .getColumnIndex(ProviderTableMeta.OCSHARES_SHARED_DATE)));
1043 share.setExpirationDate(c.getLong(c
1044 .getColumnIndex(ProviderTableMeta.OCSHARES_EXPIRATION_DATE)));
1045 share.setToken(c.getString(c
1046 .getColumnIndex(ProviderTableMeta.OCSHARES_TOKEN)));
1047 share.setSharedWithDisplayName(c.getString(c
1048 .getColumnIndex(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME)));
1049 share.setIsFolder(c.getInt(
1050 c.getColumnIndex(ProviderTableMeta.OCSHARES_IS_DIRECTORY)) == 1 ? true : false);
1051 share.setUserId(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_USER_ID)));
1052 share.setIdRemoteShared(
1053 c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED))
1054 );
1055
1056 }
1057 return share;
1058 }
1059
1060 private boolean shareExists(String cmp_key, String value) {
1061 Cursor c;
1062 if (getContentResolver() != null) {
1063 c = getContentResolver()
1064 .query(ProviderTableMeta.CONTENT_URI_SHARE,
1065 null,
1066 cmp_key + "=? AND "
1067 + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER
1068 + "=?",
1069 new String[] { value, mAccount.name }, null);
1070 } else {
1071 try {
1072 c = getContentProviderClient().query(
1073 ProviderTableMeta.CONTENT_URI_SHARE,
1074 null,
1075 cmp_key + "=? AND "
1076 + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?",
1077 new String[] { value, mAccount.name }, null);
1078 } catch (RemoteException e) {
1079 Log_OC.e(TAG,
1080 "Couldn't determine file existance, assuming non existance: "
1081 + e.getMessage());
1082 return false;
1083 }
1084 }
1085 boolean retval = c.moveToFirst();
1086 c.close();
1087 return retval;
1088 }
1089
1090 private boolean shareExists(long remoteId) {
1091 return shareExists(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, String.valueOf(remoteId));
1092 }
1093
1094 private void cleanSharedFiles() {
1095 ContentValues cv = new ContentValues();
1096 cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, false);
1097 cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, "");
1098 String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?";
1099 String [] whereArgs = new String[]{mAccount.name};
1100
1101 if (getContentResolver() != null) {
1102 getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs);
1103
1104 } else {
1105 try {
1106 getContentProviderClient().update(
1107 ProviderTableMeta.CONTENT_URI, cv, where, whereArgs
1108 );
1109
1110 } catch (RemoteException e) {
1111 Log_OC.e(TAG, "Exception in cleanSharedFiles" + e.getMessage());
1112 }
1113 }
1114 }
1115
1116 private void cleanSharedFilesInFolder(OCFile folder) {
1117 ContentValues cv = new ContentValues();
1118 cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, false);
1119 cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, "");
1120 String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " +
1121 ProviderTableMeta.FILE_PARENT + "=?";
1122 String [] whereArgs = new String[] { mAccount.name , String.valueOf(folder.getFileId()) };
1123
1124 if (getContentResolver() != null) {
1125 getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs);
1126
1127 } else {
1128 try {
1129 getContentProviderClient().update(
1130 ProviderTableMeta.CONTENT_URI, cv, where, whereArgs
1131 );
1132
1133 } catch (RemoteException e) {
1134 Log_OC.e(TAG, "Exception in cleanSharedFilesInFolder " + e.getMessage());
1135 }
1136 }
1137 }
1138
1139 private void cleanShares() {
1140 String where = ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?";
1141 String [] whereArgs = new String[]{mAccount.name};
1142
1143 if (getContentResolver() != null) {
1144 getContentResolver().delete(ProviderTableMeta.CONTENT_URI_SHARE, where, whereArgs);
1145
1146 } else {
1147 try {
1148 getContentProviderClient().delete(
1149 ProviderTableMeta.CONTENT_URI_SHARE, where, whereArgs
1150 );
1151
1152 } catch (RemoteException e) {
1153 Log_OC.e(TAG, "Exception in cleanShares" + e.getMessage());
1154 }
1155 }
1156 }
1157
1158 public void saveShares(Collection<OCShare> shares) {
1159 cleanShares();
1160 if (shares != null) {
1161 ArrayList<ContentProviderOperation> operations =
1162 new ArrayList<ContentProviderOperation>(shares.size());
1163
1164 // prepare operations to insert or update files to save in the given folder
1165 for (OCShare share : shares) {
1166 ContentValues cv = new ContentValues();
1167 cv.put(ProviderTableMeta.OCSHARES_FILE_SOURCE, share.getFileSource());
1168 cv.put(ProviderTableMeta.OCSHARES_ITEM_SOURCE, share.getItemSource());
1169 cv.put(ProviderTableMeta.OCSHARES_SHARE_TYPE, share.getShareType().getValue());
1170 cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH, share.getShareWith());
1171 cv.put(ProviderTableMeta.OCSHARES_PATH, share.getPath());
1172 cv.put(ProviderTableMeta.OCSHARES_PERMISSIONS, share.getPermissions());
1173 cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
1174 cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
1175 cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
1176 cv.put(
1177 ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME,
1178 share.getSharedWithDisplayName()
1179 );
1180 cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
1181 cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
1182 cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getIdRemoteShared());
1183 cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, mAccount.name);
1184
1185 if (shareExists(share.getIdRemoteShared())) {
1186 // updating an existing file
1187 operations.add(
1188 ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI_SHARE).
1189 withValues(cv).
1190 withSelection(
1191 ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?",
1192 new String[] { String.valueOf(share.getIdRemoteShared()) }
1193 ).
1194 build()
1195 );
1196
1197 } else {
1198 // adding a new file
1199 operations.add(
1200 ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI_SHARE).
1201 withValues(cv).
1202 build()
1203 );
1204 }
1205 }
1206
1207 // apply operations in batch
1208 if (operations.size() > 0) {
1209 @SuppressWarnings("unused")
1210 ContentProviderResult[] results = null;
1211 Log_OC.d(TAG, "Sending " + operations.size() +
1212 " operations to FileContentProvider");
1213 try {
1214 if (getContentResolver() != null) {
1215 results = getContentResolver().applyBatch(
1216 MainApp.getAuthority(), operations
1217 );
1218
1219 } else {
1220 results = getContentProviderClient().applyBatch(operations);
1221 }
1222
1223 } catch (OperationApplicationException e) {
1224 Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
1225
1226 } catch (RemoteException e) {
1227 Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
1228 }
1229 }
1230 }
1231
1232 }
1233
1234 public void updateSharedFiles(Collection<OCFile> sharedFiles) {
1235 cleanSharedFiles();
1236
1237 if (sharedFiles != null) {
1238 ArrayList<ContentProviderOperation> operations =
1239 new ArrayList<ContentProviderOperation>(sharedFiles.size());
1240
1241 // prepare operations to insert or update files to save in the given folder
1242 for (OCFile file : sharedFiles) {
1243 ContentValues cv = new ContentValues();
1244 cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
1245 cv.put(
1246 ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
1247 file.getModificationTimestampAtLastSyncForData()
1248 );
1249 cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
1250 cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
1251 cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
1252 cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
1253 cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
1254 cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
1255 if (!file.isFolder()) {
1256 cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
1257 }
1258 cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
1259 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
1260 cv.put(
1261 ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA,
1262 file.getLastSyncDateForData()
1263 );
1264 cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
1265 cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
1266 cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
1267 cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
1268 cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
1269 cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
1270 cv.put(
1271 ProviderTableMeta.FILE_UPDATE_THUMBNAIL,
1272 file.needsUpdateThumbnail() ? 1 : 0
1273 );
1274 cv.put(
1275 ProviderTableMeta.FILE_IS_DOWNLOADING,
1276 file.isDownloading() ? 1 : 0
1277 );
1278
1279 boolean existsByPath = fileExists(file.getRemotePath());
1280 if (existsByPath || fileExists(file.getFileId())) {
1281 // updating an existing file
1282 operations.add(
1283 ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
1284 withValues(cv).
1285 withSelection(
1286 ProviderTableMeta._ID + "=?",
1287 new String[] { String.valueOf(file.getFileId()) }
1288 ).build()
1289 );
1290
1291 } else {
1292 // adding a new file
1293 operations.add(
1294 ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).
1295 withValues(cv).
1296 build()
1297 );
1298 }
1299 }
1300
1301 // apply operations in batch
1302 if (operations.size() > 0) {
1303 @SuppressWarnings("unused")
1304 ContentProviderResult[] results = null;
1305 Log_OC.d(TAG, "Sending " + operations.size() +
1306 " operations to FileContentProvider");
1307 try {
1308 if (getContentResolver() != null) {
1309 results = getContentResolver().applyBatch(
1310 MainApp.getAuthority(), operations
1311 );
1312
1313 } else {
1314 results = getContentProviderClient().applyBatch(operations);
1315 }
1316
1317 } catch (OperationApplicationException e) {
1318 Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
1319
1320 } catch (RemoteException e) {
1321 Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
1322 }
1323 }
1324 }
1325
1326 }
1327
1328 public void removeShare(OCShare share){
1329 Uri share_uri = ProviderTableMeta.CONTENT_URI_SHARE;
1330 String where = ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?" + " AND " +
1331 ProviderTableMeta.FILE_PATH + "=?";
1332 String [] whereArgs = new String[]{mAccount.name, share.getPath()};
1333 if (getContentProviderClient() != null) {
1334 try {
1335 getContentProviderClient().delete(share_uri, where, whereArgs);
1336 } catch (RemoteException e) {
1337 e.printStackTrace();
1338 }
1339 } else {
1340 getContentResolver().delete(share_uri, where, whereArgs);
1341 }
1342 }
1343
1344 public void saveSharesDB(ArrayList<OCShare> shares) {
1345 saveShares(shares);
1346
1347 ArrayList<OCFile> sharedFiles = new ArrayList<OCFile>();
1348
1349 for (OCShare share : shares) {
1350 // Get the path
1351 String path = share.getPath();
1352 if (share.isFolder()) {
1353 path = path + FileUtils.PATH_SEPARATOR;
1354 }
1355
1356 // Update OCFile with data from share: ShareByLink and publicLink
1357 OCFile file = getFileByPath(path);
1358 if (file != null) {
1359 if (share.getShareType().equals(ShareType.PUBLIC_LINK)) {
1360 file.setShareByLink(true);
1361 sharedFiles.add(file);
1362 }
1363 }
1364 }
1365
1366 updateSharedFiles(sharedFiles);
1367 }
1368
1369
1370 public void saveSharesInFolder(ArrayList<OCShare> shares, OCFile folder) {
1371 cleanSharedFilesInFolder(folder);
1372 ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
1373 operations = prepareRemoveSharesInFolder(folder, operations);
1374
1375 if (shares != null) {
1376 // prepare operations to insert or update files to save in the given folder
1377 for (OCShare share : shares) {
1378 ContentValues cv = new ContentValues();
1379 cv.put(ProviderTableMeta.OCSHARES_FILE_SOURCE, share.getFileSource());
1380 cv.put(ProviderTableMeta.OCSHARES_ITEM_SOURCE, share.getItemSource());
1381 cv.put(ProviderTableMeta.OCSHARES_SHARE_TYPE, share.getShareType().getValue());
1382 cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH, share.getShareWith());
1383 cv.put(ProviderTableMeta.OCSHARES_PATH, share.getPath());
1384 cv.put(ProviderTableMeta.OCSHARES_PERMISSIONS, share.getPermissions());
1385 cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
1386 cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
1387 cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
1388 cv.put(
1389 ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME,
1390 share.getSharedWithDisplayName()
1391 );
1392 cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
1393 cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
1394 cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getIdRemoteShared());
1395 cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, mAccount.name);
1396
1397 /*
1398 if (shareExists(share.getIdRemoteShared())) {
1399 // updating an existing share resource
1400 operations.add(
1401 ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI_SHARE).
1402 withValues(cv).
1403 withSelection( ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?",
1404 new String[] { String.valueOf(share.getIdRemoteShared()) })
1405 .build());
1406
1407 } else {
1408 */
1409 // adding a new share resource
1410 operations.add(
1411 ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI_SHARE).
1412 withValues(cv).
1413 build()
1414 );
1415 //}
1416 }
1417 }
1418
1419 // apply operations in batch
1420 if (operations.size() > 0) {
1421 @SuppressWarnings("unused")
1422 ContentProviderResult[] results = null;
1423 Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
1424 try {
1425 if (getContentResolver() != null) {
1426 results = getContentResolver().applyBatch(MainApp.getAuthority(), operations);
1427
1428 } else {
1429 results = getContentProviderClient().applyBatch(operations);
1430 }
1431
1432 } catch (OperationApplicationException e) {
1433 Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
1434
1435 } catch (RemoteException e) {
1436 Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
1437 }
1438 }
1439 //}
1440
1441 }
1442
1443 private ArrayList<ContentProviderOperation> prepareRemoveSharesInFolder(
1444 OCFile folder, ArrayList<ContentProviderOperation> preparedOperations
1445 ) {
1446 if (folder != null) {
1447 String where = ProviderTableMeta.OCSHARES_PATH + "=?" + " AND "
1448 + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?";
1449 String [] whereArgs = new String[]{ "", mAccount.name };
1450
1451 Vector<OCFile> files = getFolderContent(folder);
1452
1453 for (OCFile file : files) {
1454 whereArgs[0] = file.getRemotePath();
1455 preparedOperations.add(
1456 ContentProviderOperation.newDelete(ProviderTableMeta.CONTENT_URI_SHARE).
1457 withSelection(where, whereArgs).
1458 build()
1459 );
1460 }
1461 }
1462 return preparedOperations;
1463
1464 /*
1465 if (operations.size() > 0) {
1466 try {
1467 if (getContentResolver() != null) {
1468 getContentResolver().applyBatch(MainApp.getAuthority(), operations);
1469
1470 } else {
1471 getContentProviderClient().applyBatch(operations);
1472 }
1473
1474 } catch (OperationApplicationException e) {
1475 Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
1476
1477 } catch (RemoteException e) {
1478 Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
1479 }
1480 }
1481 */
1482
1483 /*
1484 if (getContentResolver() != null) {
1485
1486 getContentResolver().delete(ProviderTableMeta.CONTENT_URI_SHARE,
1487 where,
1488 whereArgs);
1489 } else {
1490 try {
1491 getContentProviderClient().delete( ProviderTableMeta.CONTENT_URI_SHARE,
1492 where,
1493 whereArgs);
1494
1495 } catch (RemoteException e) {
1496 Log_OC.e(TAG, "Exception deleting shares in a folder " + e.getMessage());
1497 }
1498 }
1499 */
1500 //}
1501 }
1502
1503 public void triggerMediaScan(String path) {
1504 Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
1505 intent.setData(Uri.fromFile(new File(path)));
1506 MainApp.getAppContext().sendBroadcast(intent);
1507 }
1508
1509 public void deleteFileInMediaScan(String path) {
1510
1511 String mimetypeString = FileStorageUtils.getMimeTypeFromName(path);
1512 ContentResolver contentResolver = getContentResolver();
1513
1514 if (contentResolver != null) {
1515 if (mimetypeString.startsWith("image/")) {
1516 // Images
1517 contentResolver.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
1518 MediaStore.Images.Media.DATA + "=?", new String[]{path});
1519 } else if (mimetypeString.startsWith("audio/")) {
1520 // Audio
1521 contentResolver.delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
1522 MediaStore.Audio.Media.DATA + "=?", new String[]{path});
1523 } else if (mimetypeString.startsWith("video/")) {
1524 // Video
1525 contentResolver.delete(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
1526 MediaStore.Video.Media.DATA + "=?", new String[]{path});
1527 }
1528 } else {
1529 ContentProviderClient contentProviderClient = getContentProviderClient();
1530 try {
1531 if (mimetypeString.startsWith("image/")) {
1532 // Images
1533 contentProviderClient.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
1534 MediaStore.Images.Media.DATA + "=?", new String[]{path});
1535 } else if (mimetypeString.startsWith("audio/")) {
1536 // Audio
1537 contentProviderClient.delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
1538 MediaStore.Audio.Media.DATA + "=?", new String[]{path});
1539 } else if (mimetypeString.startsWith("video/")) {
1540 // Video
1541 contentProviderClient.delete(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
1542 MediaStore.Video.Media.DATA + "=?", new String[]{path});
1543 }
1544 } catch (RemoteException e) {
1545 Log_OC.e(TAG, "Exception deleting media file in MediaStore " + e.getMessage());
1546 }
1547 }
1548
1549 }
1550
1551 }