[tx-robot] updated from transifex
[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.HashSet;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Set;
31 import java.util.Vector;
32
33 import android.accounts.Account;
34 import android.content.ContentProviderClient;
35 import android.content.ContentProviderOperation;
36 import android.content.ContentProviderResult;
37 import android.content.ContentResolver;
38 import android.content.ContentUris;
39 import android.content.ContentValues;
40 import android.content.Intent;
41 import android.content.OperationApplicationException;
42 import android.database.Cursor;
43 import android.net.Uri;
44 import android.os.RemoteException;
45 import android.provider.MediaStore;
46
47 import com.owncloud.android.MainApp;
48 import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
49 import com.owncloud.android.lib.common.utils.Log_OC;
50 import com.owncloud.android.lib.resources.shares.OCShare;
51 import com.owncloud.android.lib.resources.shares.ShareType;
52 import com.owncloud.android.lib.resources.status.CapabilityBooleanType;
53 import com.owncloud.android.lib.resources.status.OCCapability;
54 import com.owncloud.android.utils.FileStorageUtils;
55
56 public class FileDataStorageManager {
57
58 public static final int ROOT_PARENT_ID = 0;
59
60 private ContentResolver mContentResolver;
61 private ContentProviderClient mContentProviderClient;
62 private Account mAccount;
63
64 private static String TAG = FileDataStorageManager.class.getSimpleName();
65
66
67 public FileDataStorageManager(Account account, ContentResolver cr) {
68 mContentProviderClient = null;
69 mContentResolver = cr;
70 mAccount = account;
71 }
72
73 public FileDataStorageManager(Account account, ContentProviderClient cp) {
74 mContentProviderClient = cp;
75 mContentResolver = null;
76 mAccount = account;
77 }
78
79
80 public void setAccount(Account account) {
81 mAccount = account;
82 }
83
84 public Account getAccount() {
85 return mAccount;
86 }
87
88 public ContentResolver getContentResolver() {
89 return mContentResolver;
90 }
91
92 public ContentProviderClient getContentProviderClient() {
93 return mContentProviderClient;
94 }
95
96
97 public OCFile getFileByPath(String path) {
98 Cursor c = getCursorForValue(ProviderTableMeta.FILE_PATH, path);
99 OCFile file = null;
100 if (c.moveToFirst()) {
101 file = createFileInstance(c);
102 }
103 c.close();
104 if (file == null && OCFile.ROOT_PATH.equals(path)) {
105 return createRootDir(); // root should always exist
106 }
107 return file;
108 }
109
110
111 public OCFile getFileById(long id) {
112 Cursor c = getCursorForValue(ProviderTableMeta._ID, String.valueOf(id));
113 OCFile file = null;
114 if (c.moveToFirst()) {
115 file = createFileInstance(c);
116 }
117 c.close();
118 return file;
119 }
120
121 public OCFile getFileByLocalPath(String path) {
122 Cursor c = getCursorForValue(ProviderTableMeta.FILE_STORAGE_PATH, path);
123 OCFile file = null;
124 if (c.moveToFirst()) {
125 file = createFileInstance(c);
126 }
127 c.close();
128 return file;
129 }
130
131 public boolean fileExists(long id) {
132 return fileExists(ProviderTableMeta._ID, String.valueOf(id));
133 }
134
135 public boolean fileExists(String path) {
136 return fileExists(ProviderTableMeta.FILE_PATH, path);
137 }
138
139
140 public Vector<OCFile> getFolderContent(OCFile f/*, boolean onlyOnDevice*/) {
141 if (f != null && f.isFolder() && f.getFileId() != -1) {
142 // TODO Enable when "On Device" is recovered ?
143 return getFolderContent(f.getFileId()/*, onlyOnDevice*/);
144
145 } else {
146 return new Vector<OCFile>();
147 }
148 }
149
150
151 public Vector<OCFile> getFolderImages(OCFile folder/*, boolean onlyOnDevice*/) {
152 Vector<OCFile> ret = new Vector<OCFile>();
153 if (folder != null) {
154 // TODO better implementation, filtering in the access to database instead of here
155 // TODO Enable when "On Device" is recovered ?
156 Vector<OCFile> tmp = getFolderContent(folder/*, onlyOnDevice*/);
157 OCFile current = null;
158 for (int i=0; i<tmp.size(); i++) {
159 current = tmp.get(i);
160 if (current.isImage()) {
161 ret.add(current);
162 }
163 }
164 }
165 return ret;
166 }
167
168 public boolean saveFile(OCFile file) {
169 boolean overriden = false;
170 ContentValues cv = new ContentValues();
171 cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
172 cv.put(
173 ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
174 file.getModificationTimestampAtLastSyncForData()
175 );
176 cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
177 cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
178 cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
179 cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
180 cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
181 cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
182 if (!file.isFolder())
183 cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
184 cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
185 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
186 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
187 cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.isFavorite() ? 1 : 0);
188 cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
189 cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, file.isSharedViaLink() ? 1 : 0);
190 cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, file.isSharedWithSharee() ? 1 : 0);
191 cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
192 cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
193 cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
194 cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail());
195 cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading());
196 cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict());
197
198 boolean sameRemotePath = fileExists(file.getRemotePath());
199 if (sameRemotePath ||
200 fileExists(file.getFileId())) { // for renamed files; no more delete and create
201
202 OCFile oldFile;
203 if (sameRemotePath) {
204 oldFile = getFileByPath(file.getRemotePath());
205 file.setFileId(oldFile.getFileId());
206 } else {
207 oldFile = getFileById(file.getFileId());
208 }
209
210 overriden = true;
211 if (getContentResolver() != null) {
212 getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv,
213 ProviderTableMeta._ID + "=?",
214 new String[]{String.valueOf(file.getFileId())});
215 } else {
216 try {
217 getContentProviderClient().update(ProviderTableMeta.CONTENT_URI,
218 cv, ProviderTableMeta._ID + "=?",
219 new String[]{String.valueOf(file.getFileId())});
220 } catch (RemoteException e) {
221 Log_OC.e(TAG,
222 "Fail to insert insert file to database "
223 + e.getMessage());
224 }
225 }
226 } else {
227 Uri result_uri = null;
228 if (getContentResolver() != null) {
229 result_uri = getContentResolver().insert(
230 ProviderTableMeta.CONTENT_URI_FILE, cv);
231 } else {
232 try {
233 result_uri = getContentProviderClient().insert(
234 ProviderTableMeta.CONTENT_URI_FILE, cv);
235 } catch (RemoteException e) {
236 Log_OC.e(TAG,
237 "Fail to insert insert file to database "
238 + e.getMessage());
239 }
240 }
241 if (result_uri != null) {
242 long new_id = Long.parseLong(result_uri.getPathSegments()
243 .get(1));
244 file.setFileId(new_id);
245 }
246 }
247
248 return overriden;
249 }
250
251
252 /**
253 * Inserts or updates the list of files contained in a given folder.
254 * <p/>
255 * CALLER IS THE RESPONSIBLE FOR GRANTING RIGHT UPDATE OF INFORMATION, NOT THIS METHOD.
256 * HERE ONLY DATA CONSISTENCY SHOULD BE GRANTED
257 *
258 * @param folder
259 * @param updatedFiles
260 * @param filesToRemove
261 */
262 public void saveFolder(
263 OCFile folder, Collection<OCFile> updatedFiles, Collection<OCFile> filesToRemove
264 ) {
265
266 Log_OC.d(TAG, "Saving folder " + folder.getRemotePath() + " with " + updatedFiles.size()
267 + " children and " + filesToRemove.size() + " files to remove");
268
269 ArrayList<ContentProviderOperation> operations =
270 new ArrayList<ContentProviderOperation>(updatedFiles.size());
271
272 // prepare operations to insert or update files to save in the given folder
273 for (OCFile file : updatedFiles) {
274 ContentValues cv = new ContentValues();
275 cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
276 cv.put(
277 ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
278 file.getModificationTimestampAtLastSyncForData()
279 );
280 cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
281 cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
282 cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
283 cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
284 //cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
285 cv.put(ProviderTableMeta.FILE_PARENT, folder.getFileId());
286 cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
287 if (!file.isFolder()) {
288 cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
289 }
290 cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
291 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
292 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
293 cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.isFavorite() ? 1 : 0);
294 cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
295 cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, file.isSharedViaLink() ? 1 : 0);
296 cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, file.isSharedWithSharee() ? 1 : 0);
297 cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
298 cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
299 cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
300 cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail());
301 cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading());
302 cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict());
303
304 boolean existsByPath = fileExists(file.getRemotePath());
305 if (existsByPath || fileExists(file.getFileId())) {
306 // updating an existing file
307 operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
308 withValues(cv).
309 withSelection(ProviderTableMeta._ID + "=?",
310 new String[]{String.valueOf(file.getFileId())})
311 .build());
312
313 } else {
314 // adding a new file
315 operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).
316 withValues(cv).build());
317 }
318 }
319
320 // prepare operations to remove files in the given folder
321 String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " +
322 ProviderTableMeta.FILE_PATH + "=?";
323 String [] whereArgs = null;
324 for (OCFile file : filesToRemove) {
325 if (file.getParentId() == folder.getFileId()) {
326 whereArgs = new String[]{mAccount.name, file.getRemotePath()};
327 if (file.isFolder()) {
328 operations.add(ContentProviderOperation.newDelete(
329 ContentUris.withAppendedId(
330 ProviderTableMeta.CONTENT_URI_DIR, file.getFileId()
331 )
332 ).withSelection(where, whereArgs).build());
333
334 File localFolder =
335 new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
336 if (localFolder.exists()) {
337 removeLocalFolder(localFolder);
338 }
339 } else {
340 operations.add(ContentProviderOperation.newDelete(
341 ContentUris.withAppendedId(
342 ProviderTableMeta.CONTENT_URI_FILE, file.getFileId()
343 )
344 ).withSelection(where, whereArgs).build());
345
346 if (file.isDown()) {
347 String path = file.getStoragePath();
348 new File(path).delete();
349 triggerMediaScan(path); // notify MediaScanner about removed file
350 }
351 }
352 }
353 }
354
355 // update metadata of folder
356 ContentValues cv = new ContentValues();
357 cv.put(ProviderTableMeta.FILE_MODIFIED, folder.getModificationTimestamp());
358 cv.put(
359 ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
360 folder.getModificationTimestampAtLastSyncForData()
361 );
362 cv.put(ProviderTableMeta.FILE_CREATION, folder.getCreationTimestamp());
363 cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, 0);
364 cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, folder.getMimetype());
365 cv.put(ProviderTableMeta.FILE_NAME, folder.getFileName());
366 cv.put(ProviderTableMeta.FILE_PARENT, folder.getParentId());
367 cv.put(ProviderTableMeta.FILE_PATH, folder.getRemotePath());
368 cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
369 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, folder.getLastSyncDateForProperties());
370 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, folder.getLastSyncDateForData());
371 cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, folder.isFavorite() ? 1 : 0);
372 cv.put(ProviderTableMeta.FILE_ETAG, folder.getEtag());
373 cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, folder.isSharedViaLink() ? 1 : 0);
374 cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, folder.isSharedWithSharee() ? 1 : 0);
375 cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, folder.getPublicLink());
376 cv.put(ProviderTableMeta.FILE_PERMISSIONS, folder.getPermissions());
377 cv.put(ProviderTableMeta.FILE_REMOTE_ID, folder.getRemoteId());
378
379 operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
380 withValues(cv).
381 withSelection(ProviderTableMeta._ID + "=?",
382 new String[]{String.valueOf(folder.getFileId())})
383 .build());
384
385 // apply operations in batch
386 ContentProviderResult[] results = null;
387 Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
388 try {
389 if (getContentResolver() != null) {
390 results = getContentResolver().applyBatch(MainApp.getAuthority(), operations);
391
392 } else {
393 results = getContentProviderClient().applyBatch(operations);
394 }
395
396 } catch (OperationApplicationException e) {
397 Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
398
399 } catch (RemoteException e) {
400 Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
401 }
402
403 // update new id in file objects for insertions
404 if (results != null) {
405 long newId;
406 Iterator<OCFile> filesIt = updatedFiles.iterator();
407 OCFile file = null;
408 for (int i = 0; i < results.length; i++) {
409 if (filesIt.hasNext()) {
410 file = filesIt.next();
411 } else {
412 file = null;
413 }
414 if (results[i].uri != null) {
415 newId = Long.parseLong(results[i].uri.getPathSegments().get(1));
416 //updatedFiles.get(i).setFileId(newId);
417 if (file != null) {
418 file.setFileId(newId);
419 }
420 }
421 }
422 }
423
424 }
425
426
427 public boolean removeFile(OCFile file, boolean removeDBData, boolean removeLocalCopy) {
428 boolean success = true;
429 if (file != null) {
430 if (file.isFolder()) {
431 success = removeFolder(file, removeDBData, removeLocalCopy);
432
433 } else {
434 if (removeDBData) {
435 //Uri file_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE,
436 // ""+file.getFileId());
437 Uri file_uri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE,
438 file.getFileId());
439 String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " +
440 ProviderTableMeta.FILE_PATH + "=?";
441 String[] whereArgs = new String[]{mAccount.name, file.getRemotePath()};
442 int deleted = 0;
443 if (getContentProviderClient() != null) {
444 try {
445 deleted = getContentProviderClient().delete(file_uri, where, whereArgs);
446 } catch (RemoteException e) {
447 e.printStackTrace();
448 }
449 } else {
450 deleted = getContentResolver().delete(file_uri, where, whereArgs);
451 }
452 success &= (deleted > 0);
453 }
454 String localPath = file.getStoragePath();
455 if (removeLocalCopy && file.isDown() && localPath != null && success) {
456 success = new File(localPath).delete();
457 if (success) {
458 deleteFileInMediaScan(localPath);
459 }
460 if (!removeDBData && success) {
461 // maybe unnecessary, but should be checked TODO remove if unnecessary
462 file.setStoragePath(null);
463 saveFile(file);
464 saveConflict(file, null);
465 }
466 }
467 }
468 }
469 return success;
470 }
471
472
473 public boolean removeFolder(OCFile folder, boolean removeDBData, boolean removeLocalContent) {
474 boolean success = true;
475 if (folder != null && folder.isFolder()) {
476 if (removeDBData && folder.getFileId() != -1) {
477 success = removeFolderInDb(folder);
478 }
479 if (removeLocalContent && success) {
480 success = removeLocalFolder(folder);
481 }
482 }
483 return success;
484 }
485
486 private boolean removeFolderInDb(OCFile folder) {
487 Uri folder_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, "" +
488 folder.getFileId()); // URI for recursive deletion
489 String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " +
490 ProviderTableMeta.FILE_PATH + "=?";
491 String [] whereArgs = new String[]{mAccount.name, folder.getRemotePath()};
492 int deleted = 0;
493 if (getContentProviderClient() != null) {
494 try {
495 deleted = getContentProviderClient().delete(folder_uri, where, whereArgs);
496 } catch (RemoteException e) {
497 e.printStackTrace();
498 }
499 } else {
500 deleted = getContentResolver().delete(folder_uri, where, whereArgs);
501 }
502 return deleted > 0;
503 }
504
505 private boolean removeLocalFolder(OCFile folder) {
506 boolean success = true;
507 String localFolderPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, folder);
508 File localFolder = new File(localFolderPath);
509 if (localFolder.exists()) {
510 // stage 1: remove the local files already registered in the files database
511 // TODO Enable when "On Device" is recovered ?
512 Vector<OCFile> files = getFolderContent(folder.getFileId()/*, false*/);
513 if (files != null) {
514 for (OCFile file : files) {
515 if (file.isFolder()) {
516 success &= removeLocalFolder(file);
517 } else {
518 if (file.isDown()) {
519 File localFile = new File(file.getStoragePath());
520 success &= localFile.delete();
521 if (success) {
522 // notify MediaScanner about removed file
523 deleteFileInMediaScan(file.getStoragePath());
524 file.setStoragePath(null);
525 saveFile(file);
526 }
527 }
528 }
529 }
530 }
531
532 // stage 2: remove the folder itself and any local file inside out of sync;
533 // for instance, after clearing the app cache or reinstalling
534 success &= removeLocalFolder(localFolder);
535 }
536 return success;
537 }
538
539 private boolean removeLocalFolder(File localFolder) {
540 boolean success = true;
541 File[] localFiles = localFolder.listFiles();
542 if (localFiles != null) {
543 for (File localFile : localFiles) {
544 if (localFile.isDirectory()) {
545 success &= removeLocalFolder(localFile);
546 } else {
547 String path = localFile.getAbsolutePath();
548 success &= localFile.delete();
549 }
550 }
551 }
552 success &= localFolder.delete();
553 return success;
554 }
555
556
557 /**
558 * Updates database and file system for a file or folder that was moved to a different location.
559 *
560 * TODO explore better (faster) implementations
561 * TODO throw exceptions up !
562 */
563 public void moveLocalFile(OCFile file, String targetPath, String targetParentPath) {
564
565 if (file != null && file.fileExists() && !OCFile.ROOT_PATH.equals(file.getFileName())) {
566
567 OCFile targetParent = getFileByPath(targetParentPath);
568 if (targetParent == null) {
569 throw new IllegalStateException(
570 "Parent folder of the target path does not exist!!");
571 }
572
573 /// 1. get all the descendants of the moved element in a single QUERY
574 Cursor c = null;
575 if (getContentProviderClient() != null) {
576 try {
577 c = getContentProviderClient().query(
578 ProviderTableMeta.CONTENT_URI,
579 null,
580 ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " +
581 ProviderTableMeta.FILE_PATH + " LIKE ? ",
582 new String[]{
583 mAccount.name,
584 file.getRemotePath() + "%"
585 },
586 ProviderTableMeta.FILE_PATH + " ASC "
587 );
588 } catch (RemoteException e) {
589 Log_OC.e(TAG, e.getMessage());
590 }
591
592 } else {
593 c = getContentResolver().query(
594 ProviderTableMeta.CONTENT_URI,
595 null,
596 ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " +
597 ProviderTableMeta.FILE_PATH + " LIKE ? ",
598 new String[]{
599 mAccount.name,
600 file.getRemotePath() + "%"
601 },
602 ProviderTableMeta.FILE_PATH + " ASC "
603 );
604 }
605
606 /// 2. prepare a batch of update operations to change all the descendants
607 ArrayList<ContentProviderOperation> operations =
608 new ArrayList<ContentProviderOperation>(c.getCount());
609 String defaultSavePath = FileStorageUtils.getSavePath(mAccount.name);
610 List<String> originalPathsToTriggerMediaScan = new ArrayList<String>();
611 List<String> newPathsToTriggerMediaScan = new ArrayList<String>();
612 if (c.moveToFirst()) {
613 int lengthOfOldPath = file.getRemotePath().length();
614 int lengthOfOldStoragePath = defaultSavePath.length() + lengthOfOldPath;
615 do {
616 ContentValues cv = new ContentValues(); // keep construction in the loop
617 OCFile child = createFileInstance(c);
618 cv.put(
619 ProviderTableMeta.FILE_PATH,
620 targetPath + child.getRemotePath().substring(lengthOfOldPath)
621 );
622 if (child.getStoragePath() != null &&
623 child.getStoragePath().startsWith(defaultSavePath)) {
624 // update link to downloaded content - but local move is not done here!
625 String targetLocalPath = defaultSavePath + targetPath +
626 child.getStoragePath().substring(lengthOfOldStoragePath);
627
628 cv.put(ProviderTableMeta.FILE_STORAGE_PATH, targetLocalPath);
629
630 originalPathsToTriggerMediaScan.add(child.getStoragePath());
631 newPathsToTriggerMediaScan.add(targetLocalPath);
632
633 }
634 if (child.getRemotePath().equals(file.getRemotePath())) {
635 cv.put(
636 ProviderTableMeta.FILE_PARENT,
637 targetParent.getFileId()
638 );
639 }
640 operations.add(
641 ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
642 withValues(cv).
643 withSelection(
644 ProviderTableMeta._ID + "=?",
645 new String[]{String.valueOf(child.getFileId())}
646 )
647 .build());
648
649 } while (c.moveToNext());
650 }
651 c.close();
652
653 /// 3. apply updates in batch
654 try {
655 if (getContentResolver() != null) {
656 getContentResolver().applyBatch(MainApp.getAuthority(), operations);
657
658 } else {
659 getContentProviderClient().applyBatch(operations);
660 }
661
662 } catch (Exception e) {
663 Log_OC.e(TAG, "Fail to update " + file.getFileId() + " and descendants in database",
664 e);
665 }
666
667 /// 4. move in local file system
668 String originalLocalPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, file);
669 String targetLocalPath = defaultSavePath + targetPath;
670 File localFile = new File(originalLocalPath);
671 boolean renamed = false;
672 if (localFile.exists()) {
673 File targetFile = new File(targetLocalPath);
674 File targetFolder = targetFile.getParentFile();
675 if (!targetFolder.exists()) {
676 targetFolder.mkdirs();
677 }
678 renamed = localFile.renameTo(targetFile);
679 }
680
681 if (renamed) {
682 Iterator<String> it = originalPathsToTriggerMediaScan.iterator();
683 while (it.hasNext()) {
684 // Notify MediaScanner about removed file
685 deleteFileInMediaScan(it.next());
686 }
687 it = newPathsToTriggerMediaScan.iterator();
688 while (it.hasNext()) {
689 // Notify MediaScanner about new file/folder
690 triggerMediaScan(it.next());
691 }
692 }
693 }
694
695 }
696
697 public void copyLocalFile(OCFile file, String targetPath) {
698
699 if (file != null && file.fileExists() && !OCFile.ROOT_PATH.equals(file.getFileName())) {
700 String localPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, file);
701 File localFile = new File(localPath);
702 boolean copied = false;
703 String defaultSavePath = FileStorageUtils.getSavePath(mAccount.name);
704 if (localFile.exists()) {
705 File targetFile = new File(defaultSavePath + targetPath);
706 File targetFolder = targetFile.getParentFile();
707 if (!targetFolder.exists()) {
708 targetFolder.mkdirs();
709 }
710 copied = FileStorageUtils.copyFile(localFile, targetFile);
711 }
712 Log_OC.d(TAG, "Local file COPIED : " + copied);
713 }
714 }
715
716 public void migrateStoredFiles(String srcPath, String dstPath) throws Exception {
717 Cursor c = null;
718 if (getContentResolver() != null) {
719 c = getContentResolver().query(ProviderTableMeta.CONTENT_URI_FILE,
720 null,
721 ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL",
722 null,
723 null);
724
725 } else {
726 try {
727 c = getContentProviderClient().query(ProviderTableMeta.CONTENT_URI_FILE,
728 new String[]{ProviderTableMeta._ID, ProviderTableMeta.FILE_STORAGE_PATH},
729 ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL",
730 null,
731 null);
732 } catch (RemoteException e) {
733 Log_OC.e(TAG, e.getMessage());
734 throw e;
735 }
736 }
737
738 ArrayList<ContentProviderOperation> operations =
739 new ArrayList<ContentProviderOperation>(c.getCount());
740 if (c.moveToFirst()) {
741 do {
742 ContentValues cv = new ContentValues();
743 long fileId = c.getLong(c.getColumnIndex(ProviderTableMeta._ID));
744 String oldFileStoragePath = c.getString(c.getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH));
745
746 if (oldFileStoragePath.startsWith(srcPath)) {
747
748 cv.put(
749 ProviderTableMeta.FILE_STORAGE_PATH,
750 oldFileStoragePath.replaceFirst(srcPath, dstPath));
751
752 operations.add(
753 ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
754 withValues(cv).
755 withSelection(
756 ProviderTableMeta._ID + "=?",
757 new String[]{String.valueOf(fileId)}
758 )
759 .build());
760 }
761
762 } while (c.moveToNext());
763 }
764 c.close();
765
766 /// 3. apply updates in batch
767 try {
768 if (getContentResolver() != null) {
769 getContentResolver().applyBatch(MainApp.getAuthority(), operations);
770
771 } else {
772 getContentProviderClient().applyBatch(operations);
773 }
774
775 } catch (Exception e) {
776 throw e;
777 }
778 }
779
780 private Vector<OCFile> getFolderContent(long parentId/*, boolean onlyOnDevice*/) {
781
782 Vector<OCFile> ret = new Vector<OCFile>();
783
784 Uri req_uri = Uri.withAppendedPath(
785 ProviderTableMeta.CONTENT_URI_DIR,
786 String.valueOf(parentId));
787 Cursor c = null;
788
789 if (getContentProviderClient() != null) {
790 try {
791 c = getContentProviderClient().query(req_uri, null,
792 ProviderTableMeta.FILE_PARENT + "=?",
793 new String[]{String.valueOf(parentId)}, null);
794 } catch (RemoteException e) {
795 Log_OC.e(TAG, e.getMessage());
796 return ret;
797 }
798 } else {
799 c = getContentResolver().query(req_uri, null,
800 ProviderTableMeta.FILE_PARENT + "=?",
801 new String[]{String.valueOf(parentId)}, null);
802 }
803
804 if (c.moveToFirst()) {
805 do {
806 OCFile child = createFileInstance(c);
807 // TODO Enable when "On Device" is recovered ?
808 // if (child.isFolder() || !onlyOnDevice || onlyOnDevice && child.isDown()){
809 ret.add(child);
810 // }
811 } while (c.moveToNext());
812 }
813
814 c.close();
815
816 Collections.sort(ret);
817
818 return ret;
819 }
820
821
822 private OCFile createRootDir() {
823 OCFile file = new OCFile(OCFile.ROOT_PATH);
824 file.setMimetype("DIR");
825 file.setParentId(FileDataStorageManager.ROOT_PARENT_ID);
826 saveFile(file);
827 return file;
828 }
829
830 private boolean fileExists(String cmp_key, String value) {
831 Cursor c;
832 if (getContentResolver() != null) {
833 c = getContentResolver()
834 .query(ProviderTableMeta.CONTENT_URI,
835 null,
836 cmp_key + "=? AND "
837 + ProviderTableMeta.FILE_ACCOUNT_OWNER
838 + "=?",
839 new String[]{value, mAccount.name}, null);
840 } else {
841 try {
842 c = getContentProviderClient().query(
843 ProviderTableMeta.CONTENT_URI,
844 null,
845 cmp_key + "=? AND "
846 + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",
847 new String[]{value, mAccount.name}, null);
848 } catch (RemoteException e) {
849 Log_OC.e(TAG,
850 "Couldn't determine file existance, assuming non existance: "
851 + e.getMessage());
852 return false;
853 }
854 }
855 boolean retval = c.moveToFirst();
856 c.close();
857 return retval;
858 }
859
860 private Cursor getCursorForValue(String key, String value) {
861 Cursor c = null;
862 if (getContentResolver() != null) {
863 c = getContentResolver()
864 .query(ProviderTableMeta.CONTENT_URI,
865 null,
866 key + "=? AND "
867 + ProviderTableMeta.FILE_ACCOUNT_OWNER
868 + "=?",
869 new String[]{value, mAccount.name}, null);
870 } else {
871 try {
872 c = getContentProviderClient().query(
873 ProviderTableMeta.CONTENT_URI,
874 null,
875 key + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER
876 + "=?", new String[]{value, mAccount.name},
877 null);
878 } catch (RemoteException e) {
879 Log_OC.e(TAG, "Could not get file details: " + e.getMessage());
880 c = null;
881 }
882 }
883 return c;
884 }
885
886
887 private OCFile createFileInstance(Cursor c) {
888 OCFile file = null;
889 if (c != null) {
890 file = new OCFile(c.getString(c
891 .getColumnIndex(ProviderTableMeta.FILE_PATH)));
892 file.setFileId(c.getLong(c.getColumnIndex(ProviderTableMeta._ID)));
893 file.setParentId(c.getLong(c
894 .getColumnIndex(ProviderTableMeta.FILE_PARENT)));
895 file.setMimetype(c.getString(c
896 .getColumnIndex(ProviderTableMeta.FILE_CONTENT_TYPE)));
897 if (!file.isFolder()) {
898 file.setStoragePath(c.getString(c
899 .getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH)));
900 if (file.getStoragePath() == null) {
901 // try to find existing file and bind it with current account;
902 // with the current update of SynchronizeFolderOperation, this won't be
903 // necessary anymore after a full synchronization of the account
904 File f = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
905 if (f.exists()) {
906 file.setStoragePath(f.getAbsolutePath());
907 file.setLastSyncDateForData(f.lastModified());
908 }
909 }
910 }
911 file.setFileLength(c.getLong(c
912 .getColumnIndex(ProviderTableMeta.FILE_CONTENT_LENGTH)));
913 file.setCreationTimestamp(c.getLong(c
914 .getColumnIndex(ProviderTableMeta.FILE_CREATION)));
915 file.setModificationTimestamp(c.getLong(c
916 .getColumnIndex(ProviderTableMeta.FILE_MODIFIED)));
917 file.setModificationTimestampAtLastSyncForData(c.getLong(c
918 .getColumnIndex(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA)));
919 file.setLastSyncDateForProperties(c.getLong(c
920 .getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE)));
921 file.setLastSyncDateForData(c.getLong(c.
922 getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA)));
923 file.setFavorite(c.getInt(
924 c.getColumnIndex(ProviderTableMeta.FILE_KEEP_IN_SYNC)) == 1 ? true : false);
925 file.setEtag(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG)));
926 file.setShareViaLink(c.getInt(
927 c.getColumnIndex(ProviderTableMeta.FILE_SHARED_VIA_LINK)) == 1 ? true : false);
928 file.setShareWithSharee(c.getInt(
929 c.getColumnIndex(ProviderTableMeta.FILE_SHARED_WITH_SHAREE)) == 1 ? true : false);
930 file.setPublicLink(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PUBLIC_LINK)));
931 file.setPermissions(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PERMISSIONS)));
932 file.setRemoteId(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_REMOTE_ID)));
933 file.setNeedsUpdateThumbnail(c.getInt(
934 c.getColumnIndex(ProviderTableMeta.FILE_UPDATE_THUMBNAIL)) == 1 ? true : false);
935 file.setDownloading(c.getInt(
936 c.getColumnIndex(ProviderTableMeta.FILE_IS_DOWNLOADING)) == 1 ? true : false);
937 file.setEtagInConflict(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG_IN_CONFLICT)));
938
939 }
940 return file;
941 }
942
943 // Methods for Shares
944 public boolean saveShare(OCShare share) {
945 boolean overriden = false;
946 ContentValues cv = new ContentValues();
947 cv.put(ProviderTableMeta.OCSHARES_FILE_SOURCE, share.getFileSource());
948 cv.put(ProviderTableMeta.OCSHARES_ITEM_SOURCE, share.getItemSource());
949 cv.put(ProviderTableMeta.OCSHARES_SHARE_TYPE, share.getShareType().getValue());
950 cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH, share.getShareWith());
951 cv.put(ProviderTableMeta.OCSHARES_PATH, share.getPath());
952 cv.put(ProviderTableMeta.OCSHARES_PERMISSIONS, share.getPermissions());
953 cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
954 cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
955 cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
956 cv.put(
957 ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME,
958 share.getSharedWithDisplayName()
959 );
960 cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
961 cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
962 cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getIdRemoteShared());
963 cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, mAccount.name);
964
965 if (shareExists(share.getIdRemoteShared())) {// for renamed files; no more delete and create
966 overriden = true;
967 if (getContentResolver() != null) {
968 getContentResolver().update(ProviderTableMeta.CONTENT_URI_SHARE, cv,
969 ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?",
970 new String[]{String.valueOf(share.getIdRemoteShared())});
971 } else {
972 try {
973 getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_SHARE,
974 cv, ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?",
975 new String[]{String.valueOf(share.getIdRemoteShared())});
976 } catch (RemoteException e) {
977 Log_OC.e(TAG,
978 "Fail to insert insert file to database "
979 + e.getMessage());
980 }
981 }
982 } else {
983 Uri result_uri = null;
984 if (getContentResolver() != null) {
985 result_uri = getContentResolver().insert(
986 ProviderTableMeta.CONTENT_URI_SHARE, cv);
987 } else {
988 try {
989 result_uri = getContentProviderClient().insert(
990 ProviderTableMeta.CONTENT_URI_SHARE, cv);
991 } catch (RemoteException e) {
992 Log_OC.e(TAG,
993 "Fail to insert insert file to database "
994 + e.getMessage());
995 }
996 }
997 if (result_uri != null) {
998 long new_id = Long.parseLong(result_uri.getPathSegments()
999 .get(1));
1000 share.setId(new_id);
1001 }
1002 }
1003
1004 return overriden;
1005 }
1006
1007
1008 public OCShare getFirstShareByPathAndType(String path, ShareType type, String shareWith) {
1009 Cursor c = null;
1010
1011 String selection = ProviderTableMeta.OCSHARES_PATH + "=? AND "
1012 + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? AND "
1013 + ProviderTableMeta.OCSHARES_SHARE_WITH + "=? AND "
1014 + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?" ;
1015
1016 String [] selectionArgs = new String[]{path, Integer.toString(type.getValue()),
1017 shareWith, mAccount.name};
1018
1019 if (getContentResolver() != null) {
1020 c = getContentResolver().query(
1021 ProviderTableMeta.CONTENT_URI_SHARE,
1022 null,
1023 selection, selectionArgs,
1024 null);
1025 } else {
1026 try {
1027 c = getContentProviderClient().query(
1028 ProviderTableMeta.CONTENT_URI_SHARE,
1029 null,
1030 selection, selectionArgs,
1031 null);
1032
1033 } catch (RemoteException e) {
1034 Log_OC.e(TAG, "Could not get file details: " + e.getMessage());
1035 c = null;
1036 }
1037 }
1038 OCShare share = null;
1039 if (c.moveToFirst()) {
1040 share = createShareInstance(c);
1041 }
1042 c.close();
1043 return share;
1044 }
1045
1046 private OCShare createShareInstance(Cursor c) {
1047 OCShare share = null;
1048 if (c != null) {
1049 share = new OCShare(c.getString(c
1050 .getColumnIndex(ProviderTableMeta.OCSHARES_PATH)));
1051 share.setId(c.getLong(c.getColumnIndex(ProviderTableMeta._ID)));
1052 share.setFileSource(c.getLong(c
1053 .getColumnIndex(ProviderTableMeta.OCSHARES_ITEM_SOURCE)));
1054 share.setShareType(ShareType.fromValue(c.getInt(c
1055 .getColumnIndex(ProviderTableMeta.OCSHARES_SHARE_TYPE))));
1056 share.setShareWith(c.getString(c
1057 .getColumnIndex(ProviderTableMeta.OCSHARES_SHARE_WITH)));
1058 share.setPermissions(c.getInt(c
1059 .getColumnIndex(ProviderTableMeta.OCSHARES_PERMISSIONS)));
1060 share.setSharedDate(c.getLong(c
1061 .getColumnIndex(ProviderTableMeta.OCSHARES_SHARED_DATE)));
1062 share.setExpirationDate(c.getLong(c
1063 .getColumnIndex(ProviderTableMeta.OCSHARES_EXPIRATION_DATE)));
1064 share.setToken(c.getString(c
1065 .getColumnIndex(ProviderTableMeta.OCSHARES_TOKEN)));
1066 share.setSharedWithDisplayName(c.getString(c
1067 .getColumnIndex(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME)));
1068 share.setIsFolder(c.getInt(
1069 c.getColumnIndex(ProviderTableMeta.OCSHARES_IS_DIRECTORY)) == 1);
1070 share.setUserId(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_USER_ID)));
1071 share.setIdRemoteShared(c.getLong(
1072 c.getColumnIndex(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED)));
1073 }
1074 return share;
1075 }
1076
1077 private boolean shareExists(String cmp_key, String value) {
1078 Cursor c;
1079 if (getContentResolver() != null) {
1080 c = getContentResolver()
1081 .query(ProviderTableMeta.CONTENT_URI_SHARE,
1082 null,
1083 cmp_key + "=? AND "
1084 + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER
1085 + "=?",
1086 new String[]{value, mAccount.name}, null);
1087 } else {
1088 try {
1089 c = getContentProviderClient().query(
1090 ProviderTableMeta.CONTENT_URI_SHARE,
1091 null,
1092 cmp_key + "=? AND "
1093 + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?",
1094 new String[]{value, mAccount.name}, null);
1095 } catch (RemoteException e) {
1096 Log_OC.e(TAG,
1097 "Couldn't determine file existance, assuming non existance: "
1098 + e.getMessage());
1099 return false;
1100 }
1101 }
1102 boolean retval = c.moveToFirst();
1103 c.close();
1104 return retval;
1105 }
1106
1107 private boolean shareExists(long remoteId) {
1108 return shareExists(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, String.valueOf(remoteId));
1109 }
1110
1111 private void resetShareFlagsInAllFiles() {
1112 ContentValues cv = new ContentValues();
1113 cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, false);
1114 cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, false);
1115 cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, "");
1116 String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?";
1117 String[] whereArgs = new String[]{mAccount.name};
1118
1119 if (getContentResolver() != null) {
1120 getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs);
1121
1122 } else {
1123 try {
1124 getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, where,
1125 whereArgs);
1126 } catch (RemoteException e) {
1127 Log_OC.e(TAG, "Exception in resetShareFlagsInAllFiles" + e.getMessage());
1128 }
1129 }
1130 }
1131
1132 private void resetShareFlagsInFolder(OCFile folder) {
1133 ContentValues cv = new ContentValues();
1134 cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, false);
1135 cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, false);
1136 cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, "");
1137 String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " +
1138 ProviderTableMeta.FILE_PARENT + "=?";
1139 String [] whereArgs = new String[] { mAccount.name , String.valueOf(folder.getFileId()) };
1140
1141 if (getContentResolver() != null) {
1142 getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs);
1143
1144 } else {
1145 try {
1146 getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, where,
1147 whereArgs);
1148 } catch (RemoteException e) {
1149 Log_OC.e(TAG, "Exception in resetShareFlagsInFolder " + e.getMessage());
1150 }
1151 }
1152 }
1153
1154 private void resetShareFlagInAFile(String filePath){
1155 ContentValues cv = new ContentValues();
1156 cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, false);
1157 cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, false);
1158 cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, "");
1159 String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " +
1160 ProviderTableMeta.FILE_PATH+ "=?";
1161 String [] whereArgs = new String[] { mAccount.name , filePath };
1162
1163 if (getContentResolver() != null) {
1164 getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs);
1165
1166 } else {
1167 try {
1168 getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, where,
1169 whereArgs);
1170 } catch (RemoteException e) {
1171 Log_OC.e(TAG, "Exception in resetShareFlagsInFolder " + e.getMessage());
1172 }
1173 }
1174 }
1175
1176 private void cleanShares() {
1177 String where = ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?";
1178 String[] whereArgs = new String[]{mAccount.name};
1179
1180 if (getContentResolver() != null) {
1181 getContentResolver().delete(ProviderTableMeta.CONTENT_URI_SHARE, where, whereArgs);
1182
1183 } else {
1184 try {
1185 getContentProviderClient().delete(ProviderTableMeta.CONTENT_URI_SHARE, where,
1186 whereArgs);
1187 } catch (RemoteException e) {
1188 Log_OC.e(TAG, "Exception in cleanShares" + e.getMessage());
1189 }
1190 }
1191 }
1192
1193 public void saveShares(Collection<OCShare> shares) {
1194 cleanShares();
1195 if (shares != null) {
1196 ArrayList<ContentProviderOperation> operations =
1197 new ArrayList<ContentProviderOperation>(shares.size());
1198
1199 // prepare operations to insert or update files to save in the given folder
1200 for (OCShare share : shares) {
1201 ContentValues cv = new ContentValues();
1202 cv.put(ProviderTableMeta.OCSHARES_FILE_SOURCE, share.getFileSource());
1203 cv.put(ProviderTableMeta.OCSHARES_ITEM_SOURCE, share.getItemSource());
1204 cv.put(ProviderTableMeta.OCSHARES_SHARE_TYPE, share.getShareType().getValue());
1205 cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH, share.getShareWith());
1206 cv.put(ProviderTableMeta.OCSHARES_PATH, share.getPath());
1207 cv.put(ProviderTableMeta.OCSHARES_PERMISSIONS, share.getPermissions());
1208 cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
1209 cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
1210 cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
1211 cv.put(
1212 ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME,
1213 share.getSharedWithDisplayName()
1214 );
1215 cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
1216 cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
1217 cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getIdRemoteShared());
1218 cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, mAccount.name);
1219
1220 if (shareExists(share.getIdRemoteShared())) {
1221 // updating an existing file
1222 operations.add(
1223 ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI_SHARE).
1224 withValues(cv).
1225 withSelection(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?",
1226 new String[]{String.valueOf(share.getIdRemoteShared())})
1227 .build());
1228 } else {
1229 // adding a new file
1230 operations.add(
1231 ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI_SHARE).
1232 withValues(cv).
1233 build()
1234 );
1235 }
1236 }
1237
1238 // apply operations in batch
1239 if (operations.size() > 0) {
1240 @SuppressWarnings("unused")
1241 ContentProviderResult[] results = null;
1242 Log_OC.d(TAG, "Sending " + operations.size() +
1243 " operations to FileContentProvider");
1244 try {
1245 if (getContentResolver() != null) {
1246 results = getContentResolver().applyBatch(MainApp.getAuthority(),
1247 operations);
1248 } else {
1249 results = getContentProviderClient().applyBatch(operations);
1250 }
1251
1252 } catch (OperationApplicationException e) {
1253 Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
1254
1255 } catch (RemoteException e) {
1256 Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
1257 }
1258 }
1259 }
1260
1261 }
1262
1263 public void updateSharedFiles(Collection<OCFile> sharedFiles) {
1264 resetShareFlagsInAllFiles();
1265
1266 if (sharedFiles != null) {
1267 ArrayList<ContentProviderOperation> operations =
1268 new ArrayList<ContentProviderOperation>(sharedFiles.size());
1269
1270 // prepare operations to insert or update files to save in the given folder
1271 for (OCFile file : sharedFiles) {
1272 ContentValues cv = new ContentValues();
1273 cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
1274 cv.put(
1275 ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
1276 file.getModificationTimestampAtLastSyncForData()
1277 );
1278 cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
1279 cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
1280 cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
1281 cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
1282 cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
1283 cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
1284 if (!file.isFolder()) {
1285 cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
1286 }
1287 cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
1288 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
1289 cv.put(
1290 ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA,
1291 file.getLastSyncDateForData()
1292 );
1293 cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.isFavorite() ? 1 : 0);
1294 cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
1295 cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, file.isSharedViaLink() ? 1 : 0);
1296 cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, file.isSharedWithSharee() ? 1 : 0);
1297 cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
1298 cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
1299 cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
1300 cv.put(
1301 ProviderTableMeta.FILE_UPDATE_THUMBNAIL,
1302 file.needsUpdateThumbnail() ? 1 : 0
1303 );
1304 cv.put(
1305 ProviderTableMeta.FILE_IS_DOWNLOADING,
1306 file.isDownloading() ? 1 : 0
1307 );
1308 cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict());
1309
1310 boolean existsByPath = fileExists(file.getRemotePath());
1311 if (existsByPath || fileExists(file.getFileId())) {
1312 // updating an existing file
1313 operations.add(
1314 ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
1315 withValues(cv).
1316 withSelection(ProviderTableMeta._ID + "=?",
1317 new String[]{String.valueOf(file.getFileId())})
1318 .build());
1319
1320 } else {
1321 // adding a new file
1322 operations.add(
1323 ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).
1324 withValues(cv).
1325 build()
1326 );
1327 }
1328 }
1329
1330 // apply operations in batch
1331 if (operations.size() > 0) {
1332 @SuppressWarnings("unused")
1333 ContentProviderResult[] results = null;
1334 Log_OC.d(TAG, "Sending " + operations.size() +
1335 " operations to FileContentProvider");
1336 try {
1337 if (getContentResolver() != null) {
1338 results = getContentResolver().applyBatch(MainApp.getAuthority(), operations);
1339 } else {
1340 results = getContentProviderClient().applyBatch(operations);
1341 }
1342
1343 } catch (OperationApplicationException e) {
1344 Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
1345
1346 } catch (RemoteException e) {
1347 Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
1348 }
1349 }
1350 }
1351
1352 }
1353
1354 public void removeShare(OCShare share) {
1355 Uri share_uri = ProviderTableMeta.CONTENT_URI_SHARE;
1356 String where = ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?" + " AND " +
1357 ProviderTableMeta._ID + "=?";
1358 String [] whereArgs = new String[]{mAccount.name, Long.toString(share.getId())};
1359 if (getContentProviderClient() != null) {
1360 try {
1361 getContentProviderClient().delete(share_uri, where, whereArgs);
1362 } catch (RemoteException e) {
1363 e.printStackTrace();
1364 }
1365 } else {
1366 getContentResolver().delete(share_uri, where, whereArgs);
1367 }
1368 }
1369
1370 public void saveSharesDB(ArrayList<OCShare> shares) {
1371 ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
1372
1373 // Reset flags & Remove shares for this files
1374 String filePath = "";
1375 for (OCShare share: shares) {
1376 if (filePath != share.getPath()){
1377 filePath = share.getPath();
1378 resetShareFlagInAFile(filePath);
1379 operations = prepareRemoveSharesInFile(filePath, operations);
1380 }
1381 }
1382
1383 // Add operations to insert shares
1384 operations = prepareInsertShares(shares, operations);
1385
1386 // apply operations in batch
1387 if (operations.size() > 0) {
1388 Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
1389 try {
1390 if (getContentResolver() != null) {
1391 getContentResolver().applyBatch(MainApp.getAuthority(), operations);
1392
1393 } else {
1394 getContentProviderClient().applyBatch(operations);
1395 }
1396
1397 } catch (OperationApplicationException e) {
1398 Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
1399
1400 } catch (RemoteException e) {
1401 Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
1402 }
1403 }
1404
1405 // // TODO: review if it is needed
1406 // // Update shared files
1407 // ArrayList<OCFile> sharedFiles = new ArrayList<OCFile>();
1408 //
1409 // for (OCShare share : shares) {
1410 // // Get the path
1411 // String path = share.getPath();
1412 // if (share.isFolder()) {
1413 // path = path + FileUtils.PATH_SEPARATOR;
1414 // }
1415 //
1416 // // Update OCFile with data from share: ShareByLink, publicLink and
1417 // OCFile file = getFileByPath(path);
1418 // if (file != null) {
1419 // if (share.getShareType().equals(ShareType.PUBLIC_LINK)) {
1420 // file.setShareViaLink(true);
1421 // sharedFiles.add(file);
1422 // }
1423 // }
1424 // }
1425 //
1426 // // TODO: Review
1427 // updateSharedFiles(sharedFiles);
1428 }
1429
1430
1431 public void saveSharesInFolder(ArrayList<OCShare> shares, OCFile folder) {
1432 resetShareFlagsInFolder(folder);
1433 ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
1434 operations = prepareRemoveSharesInFolder(folder, operations);
1435
1436 if (shares != null) {
1437 // prepare operations to insert or update files to save in the given folder
1438 operations = prepareInsertShares(shares, operations);
1439 }
1440
1441 // apply operations in batch
1442 if (operations.size() > 0) {
1443 Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
1444 try {
1445 if (getContentResolver() != null) {
1446 getContentResolver().applyBatch(MainApp.getAuthority(), operations);
1447
1448 } else {
1449 getContentProviderClient().applyBatch(operations);
1450 }
1451
1452 } catch (OperationApplicationException e) {
1453 Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
1454
1455 } catch (RemoteException e) {
1456
1457 }
1458 }
1459
1460 }
1461
1462 /**
1463 * Prepare operations to insert or update files to save in the given folder
1464 * @param shares List of shares to insert
1465 * @param operations List of operations
1466 * @return
1467 */
1468 private ArrayList<ContentProviderOperation> prepareInsertShares(
1469 ArrayList<OCShare> shares, ArrayList<ContentProviderOperation> operations) {
1470
1471 if (shares != null) {
1472 // prepare operations to insert or update files to save in the given folder
1473 for (OCShare share : shares) {
1474 ContentValues cv = new ContentValues();
1475 cv.put(ProviderTableMeta.OCSHARES_FILE_SOURCE, share.getFileSource());
1476 cv.put(ProviderTableMeta.OCSHARES_ITEM_SOURCE, share.getItemSource());
1477 cv.put(ProviderTableMeta.OCSHARES_SHARE_TYPE, share.getShareType().getValue());
1478 cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH, share.getShareWith());
1479 cv.put(ProviderTableMeta.OCSHARES_PATH, share.getPath());
1480 cv.put(ProviderTableMeta.OCSHARES_PERMISSIONS, share.getPermissions());
1481 cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
1482 cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
1483 cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
1484 cv.put(
1485 ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME,
1486 share.getSharedWithDisplayName()
1487 );
1488 cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
1489 cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
1490 cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getIdRemoteShared());
1491 cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, mAccount.name);
1492
1493 // adding a new share resource
1494 operations.add(
1495 ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI_SHARE).
1496 withValues(cv).
1497 build()
1498 );
1499 }
1500 }
1501 return operations;
1502 }
1503
1504 private ArrayList<ContentProviderOperation> prepareRemoveSharesInFolder(
1505 OCFile folder, ArrayList<ContentProviderOperation> preparedOperations) {
1506 if (folder != null) {
1507 String where = ProviderTableMeta.OCSHARES_PATH + "=?" + " AND "
1508 + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?";
1509 String [] whereArgs = new String[]{ "", mAccount.name };
1510
1511 // TODO Enable when "On Device" is recovered ?
1512 Vector<OCFile> files = getFolderContent(folder /*, false*/);
1513
1514 for (OCFile file : files) {
1515 whereArgs[0] = file.getRemotePath();
1516 preparedOperations.add(
1517 ContentProviderOperation.newDelete(ProviderTableMeta.CONTENT_URI_SHARE).
1518 withSelection(where, whereArgs).
1519 build()
1520 );
1521 }
1522 }
1523 return preparedOperations;
1524
1525 }
1526
1527 private ArrayList<ContentProviderOperation> prepareRemoveSharesInFile(
1528 String filePath, ArrayList<ContentProviderOperation> preparedOperations) {
1529
1530 String where = ProviderTableMeta.OCSHARES_PATH + "=?" + " AND "
1531 + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?";
1532 String[] whereArgs = new String[]{filePath, mAccount.name};
1533
1534 preparedOperations.add(
1535 ContentProviderOperation.newDelete(ProviderTableMeta.CONTENT_URI_SHARE).
1536 withSelection(where, whereArgs).
1537 build()
1538 );
1539
1540 return preparedOperations;
1541
1542 }
1543
1544 public ArrayList<OCShare> getSharesWithForAFile(String filePath, String accountName){
1545 // Condition
1546 String where = ProviderTableMeta.OCSHARES_PATH + "=?" + " AND "
1547 + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?"+ "AND"
1548 + " (" + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? OR "
1549 + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? ) ";
1550 String [] whereArgs = new String[]{ filePath, accountName ,
1551 Integer.toString(ShareType.USER.getValue()),
1552 Integer.toString(ShareType.GROUP.getValue()) };
1553
1554 Cursor c = null;
1555 if (getContentResolver() != null) {
1556 c = getContentResolver().query(
1557 ProviderTableMeta.CONTENT_URI_SHARE,
1558 null, where, whereArgs, null);
1559 } else {
1560 try {
1561 c = getContentProviderClient().query(
1562 ProviderTableMeta.CONTENT_URI_SHARE,
1563 null, where, whereArgs, null);
1564
1565 } catch (RemoteException e) {
1566 Log_OC.e(TAG, "Could not get list of shares with: " + e.getMessage());
1567 c = null;
1568 }
1569 }
1570 ArrayList<OCShare> shares = new ArrayList<OCShare>();
1571 OCShare share = null;
1572 if (c.moveToFirst()) {
1573 do {
1574 share = createShareInstance(c);
1575 shares.add(share);
1576 // }
1577 } while (c.moveToNext());
1578 }
1579 c.close();
1580
1581 return shares;
1582 }
1583
1584 public void triggerMediaScan(String path) {
1585 Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
1586 intent.setData(Uri.fromFile(new File(path)));
1587 MainApp.getAppContext().sendBroadcast(intent);
1588 }
1589
1590 public void deleteFileInMediaScan(String path) {
1591
1592 String mimetypeString = FileStorageUtils.getMimeTypeFromName(path);
1593 ContentResolver contentResolver = getContentResolver();
1594
1595 if (contentResolver != null) {
1596 if (mimetypeString.startsWith("image/")) {
1597 // Images
1598 contentResolver.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
1599 MediaStore.Images.Media.DATA + "=?", new String[]{path});
1600 } else if (mimetypeString.startsWith("audio/")) {
1601 // Audio
1602 contentResolver.delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
1603 MediaStore.Audio.Media.DATA + "=?", new String[]{path});
1604 } else if (mimetypeString.startsWith("video/")) {
1605 // Video
1606 contentResolver.delete(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
1607 MediaStore.Video.Media.DATA + "=?", new String[]{path});
1608 }
1609 } else {
1610 ContentProviderClient contentProviderClient = getContentProviderClient();
1611 try {
1612 if (mimetypeString.startsWith("image/")) {
1613 // Images
1614 contentProviderClient.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
1615 MediaStore.Images.Media.DATA + "=?", new String[]{path});
1616 } else if (mimetypeString.startsWith("audio/")) {
1617 // Audio
1618 contentProviderClient.delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
1619 MediaStore.Audio.Media.DATA + "=?", new String[]{path});
1620 } else if (mimetypeString.startsWith("video/")) {
1621 // Video
1622 contentProviderClient.delete(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
1623 MediaStore.Video.Media.DATA + "=?", new String[]{path});
1624 }
1625 } catch (RemoteException e) {
1626 Log_OC.e(TAG, "Exception deleting media file in MediaStore " + e.getMessage());
1627 }
1628 }
1629
1630 }
1631
1632 public void saveConflict(OCFile file, String etagInConflict) {
1633 if (!file.isDown()) {
1634 etagInConflict = null;
1635 }
1636 ContentValues cv = new ContentValues();
1637 cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, etagInConflict);
1638 int updated = 0;
1639 if (getContentResolver() != null) {
1640 updated = getContentResolver().update(
1641 ProviderTableMeta.CONTENT_URI_FILE,
1642 cv,
1643 ProviderTableMeta._ID + "=?",
1644 new String[] { String.valueOf(file.getFileId())}
1645 );
1646 } else {
1647 try {
1648 updated = getContentProviderClient().update(
1649 ProviderTableMeta.CONTENT_URI_FILE,
1650 cv,
1651 ProviderTableMeta._ID + "=?",
1652 new String[]{String.valueOf(file.getFileId())}
1653 );
1654 } catch (RemoteException e) {
1655 Log_OC.e(TAG, "Failed saving conflict in database " + e.getMessage());
1656 }
1657 }
1658
1659 Log_OC.d(TAG, "Number of files updated with CONFLICT: " + updated);
1660
1661 if (updated > 0) {
1662 if (etagInConflict != null) {
1663 /// set conflict in all ancestor folders
1664
1665 long parentId = file.getParentId();
1666 Set<String> ancestorIds = new HashSet<String>();
1667 while (parentId != FileDataStorageManager.ROOT_PARENT_ID) {
1668 ancestorIds.add(Long.toString(parentId));
1669 parentId = getFileById(parentId).getParentId();
1670 }
1671
1672 if (ancestorIds.size() > 0) {
1673 StringBuffer whereBuffer = new StringBuffer();
1674 whereBuffer.append(ProviderTableMeta._ID).append(" IN (");
1675 for (int i = 0; i < ancestorIds.size() - 1; i++) {
1676 whereBuffer.append("?,");
1677 }
1678 whereBuffer.append("?");
1679 whereBuffer.append(")");
1680
1681 if (getContentResolver() != null) {
1682 updated = getContentResolver().update(
1683 ProviderTableMeta.CONTENT_URI_FILE,
1684 cv,
1685 whereBuffer.toString(),
1686 ancestorIds.toArray(new String[]{})
1687 );
1688 } else {
1689 try {
1690 updated = getContentProviderClient().update(
1691 ProviderTableMeta.CONTENT_URI_FILE,
1692 cv,
1693 whereBuffer.toString(),
1694 ancestorIds.toArray(new String[]{})
1695 );
1696 } catch (RemoteException e) {
1697 Log_OC.e(TAG, "Failed saving conflict in database " + e.getMessage());
1698 }
1699 }
1700 } // else file is ROOT folder, no parent to set in conflict
1701
1702 } else {
1703 /// update conflict in ancestor folders
1704 // (not directly unset; maybe there are more conflicts below them)
1705 String parentPath = file.getRemotePath();
1706 if (parentPath.endsWith(OCFile.PATH_SEPARATOR)) {
1707 parentPath = parentPath.substring(0, parentPath.length() - 1);
1708 }
1709 parentPath = parentPath.substring(0, parentPath.lastIndexOf(OCFile.PATH_SEPARATOR) + 1);
1710
1711 Log_OC.d(TAG, "checking parents to remove conflict; STARTING with " + parentPath);
1712 while (parentPath.length() > 0) {
1713
1714 String where =
1715 ProviderTableMeta.FILE_ETAG_IN_CONFLICT + " IS NOT NULL AND " +
1716 ProviderTableMeta.FILE_CONTENT_TYPE + " != 'DIR' AND " +
1717 ProviderTableMeta.FILE_ACCOUNT_OWNER + " = ? AND " +
1718 ProviderTableMeta.FILE_PATH + " LIKE ?";
1719 Cursor descendentsInConflict = getContentResolver().query(
1720 ProviderTableMeta.CONTENT_URI_FILE,
1721 new String[]{ProviderTableMeta._ID},
1722 where,
1723 new String[]{mAccount.name, parentPath + "%"},
1724 null
1725 );
1726 if (descendentsInConflict == null || descendentsInConflict.getCount() == 0) {
1727 Log_OC.d(TAG, "NO MORE conflicts in " + parentPath);
1728 if (getContentResolver() != null) {
1729 updated = getContentResolver().update(
1730 ProviderTableMeta.CONTENT_URI_FILE,
1731 cv,
1732 ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " +
1733 ProviderTableMeta.FILE_PATH + "=?",
1734 new String[]{mAccount.name, parentPath}
1735 );
1736 } else {
1737 try {
1738 updated = getContentProviderClient().update(
1739 ProviderTableMeta.CONTENT_URI_FILE,
1740 cv,
1741 ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " +
1742 ProviderTableMeta.FILE_PATH + "=?"
1743 , new String[]{mAccount.name, parentPath}
1744 );
1745 } catch (RemoteException e) {
1746 Log_OC.e(TAG, "Failed saving conflict in database " + e.getMessage());
1747 }
1748 }
1749
1750 } else {
1751 Log_OC.d(TAG, "STILL " + descendentsInConflict.getCount() + " in " + parentPath);
1752 }
1753
1754 if (descendentsInConflict != null) {
1755 descendentsInConflict.close();
1756 }
1757
1758 parentPath = parentPath.substring(0, parentPath.length() - 1); // trim last /
1759 parentPath = parentPath.substring(0, parentPath.lastIndexOf(OCFile.PATH_SEPARATOR) + 1);
1760 Log_OC.d(TAG, "checking parents to remove conflict; NEXT " + parentPath);
1761 }
1762 }
1763 }
1764
1765 }
1766
1767 public OCCapability saveCapabilities(OCCapability capability){
1768
1769 // Prepare capabilities data
1770 ContentValues cv = new ContentValues();
1771 cv.put(ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME, mAccount.name);
1772 cv.put(ProviderTableMeta.CAPABILITIES_VERSION_MAYOR, capability.getVersionMayor());
1773 cv.put(ProviderTableMeta.CAPABILITIES_VERSION_MINOR, capability.getVersionMinor());
1774 cv.put(ProviderTableMeta.CAPABILITIES_VERSION_MICRO, capability.getVersionMicro());
1775 cv.put(ProviderTableMeta.CAPABILITIES_VERSION_STRING, capability.getVersionString());
1776 cv.put(ProviderTableMeta.CAPABILITIES_VERSION_EDITION, capability.getVersionEdition());
1777 cv.put(ProviderTableMeta.CAPABILITIES_CORE_POLLINTERVAL, capability.getCorePollinterval());
1778 cv.put(ProviderTableMeta.CAPABILITIES_SHARING_API_ENABLED, capability.getFilesSharingApiEnabled().getValue());
1779 cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_ENABLED,
1780 capability.getFilesSharingPublicEnabled().getValue());
1781 cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_PASSWORD_ENFORCED,
1782 capability.getFilesSharingPublicPasswordEnforced().getValue());
1783 cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENABLED,
1784 capability.getFilesSharingPublicExpireDateEnabled().getValue());
1785 cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_DAYS,
1786 capability.getFilesSharingPublicExpireDateDays());
1787 cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENFORCED,
1788 capability.getFilesSharingPublicExpireDateEnforced().getValue());
1789 cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_SEND_MAIL,
1790 capability.getFilesSharingPublicSendMail().getValue());
1791 cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_UPLOAD,
1792 capability.getFilesSharingPublicUpload().getValue());
1793 cv.put(ProviderTableMeta.CAPABILITIES_SHARING_USER_SEND_MAIL,
1794 capability.getFilesSharingUserSendMail().getValue());
1795 cv.put(ProviderTableMeta.CAPABILITIES_SHARING_RESHARING, capability.getFilesSharingResharing().getValue());
1796 cv.put(ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_OUTGOING,
1797 capability.getFilesSharingFederationOutgoing().getValue());
1798 cv.put(ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_INCOMING,
1799 capability.getFilesSharingFederationIncoming().getValue());
1800 cv.put(ProviderTableMeta.CAPABILITIES_FILES_BIGFILECHUNKING, capability.getFilesBigFileChuncking().getValue());
1801 cv.put(ProviderTableMeta.CAPABILITIES_FILES_UNDELETE, capability.getFilesUndelete().getValue());
1802 cv.put(ProviderTableMeta.CAPABILITIES_FILES_VERSIONING, capability.getFilesVersioning().getValue());
1803
1804 if (capabilityExists(mAccount.name)) {
1805 if (getContentResolver() != null) {
1806 getContentResolver().update(ProviderTableMeta.CONTENT_URI_CAPABILITIES, cv,
1807 ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME + "=?",
1808 new String[]{mAccount.name});
1809 } else {
1810 try {
1811 getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_CAPABILITIES,
1812 cv, ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME + "=?",
1813 new String[]{mAccount.name});
1814 } catch (RemoteException e) {
1815 Log_OC.e(TAG,
1816 "Fail to insert insert file to database "
1817 + e.getMessage());
1818 }
1819 }
1820 } else {
1821 Uri result_uri = null;
1822 if (getContentResolver() != null) {
1823 result_uri = getContentResolver().insert(
1824 ProviderTableMeta.CONTENT_URI_CAPABILITIES, cv);
1825 } else {
1826 try {
1827 result_uri = getContentProviderClient().insert(
1828 ProviderTableMeta.CONTENT_URI_CAPABILITIES, cv);
1829 } catch (RemoteException e) {
1830 Log_OC.e(TAG,
1831 "Fail to insert insert capability to database "
1832 + e.getMessage());
1833 }
1834 }
1835 if (result_uri != null) {
1836 long new_id = Long.parseLong(result_uri.getPathSegments()
1837 .get(1));
1838 capability.setId(new_id);
1839 capability.setAccountName(mAccount.name);
1840 }
1841 }
1842
1843 return capability;
1844 }
1845
1846 private boolean capabilityExists(String accountName) {
1847 Cursor c = getCapabilityCursorForAccount(accountName);
1848 boolean exists = false;
1849 if (c != null) {
1850 exists = c.moveToFirst();
1851 c.close();
1852 }
1853 return exists;
1854 }
1855
1856 private Cursor getCapabilityCursorForAccount(String accountName){
1857 Cursor c = null;
1858 if (getContentResolver() != null) {
1859 c = getContentResolver()
1860 .query(ProviderTableMeta.CONTENT_URI_CAPABILITIES,
1861 null,
1862 ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME + "=? ",
1863 new String[]{accountName}, null);
1864 } else {
1865 try {
1866 c = getContentProviderClient().query(
1867 ProviderTableMeta.CONTENT_URI_CAPABILITIES,
1868 null,
1869 ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME + "=? ",
1870 new String[]{accountName}, null);
1871 } catch (RemoteException e) {
1872 Log_OC.e(TAG,
1873 "Couldn't determine capability existance, assuming non existance: "
1874 + e.getMessage());
1875 }
1876 }
1877
1878 return c;
1879
1880 }
1881 public OCCapability getCapability(String accountName){
1882 OCCapability capability = null;
1883 Cursor c = getCapabilityCursorForAccount(accountName);
1884
1885 if (c.moveToFirst()) {
1886 capability = createCapabilityInstance(c);
1887 }
1888 c.close();
1889 return capability;
1890 }
1891
1892 private OCCapability createCapabilityInstance(Cursor c) {
1893 OCCapability capability = null;
1894 if (c != null) {
1895 capability = new OCCapability();
1896 capability.setId(c.getLong(c.getColumnIndex(ProviderTableMeta._ID)));
1897 capability.setAccountName(c.getString(c
1898 .getColumnIndex(ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME)));
1899 capability.setVersionMayor(c.getInt(c
1900 .getColumnIndex(ProviderTableMeta.CAPABILITIES_VERSION_MAYOR)));
1901 capability.setVersionMinor(c.getInt(c
1902 .getColumnIndex(ProviderTableMeta.CAPABILITIES_VERSION_MINOR)));
1903 capability.setVersionMicro(c.getInt(c
1904 .getColumnIndex(ProviderTableMeta.CAPABILITIES_VERSION_MICRO)));
1905 capability.setVersionString(c.getString(c
1906 .getColumnIndex(ProviderTableMeta.CAPABILITIES_VERSION_STRING)));
1907 capability.setVersionEdition(c.getString(c
1908 .getColumnIndex(ProviderTableMeta.CAPABILITIES_VERSION_EDITION)));
1909 capability.setCorePollinterval(c.getInt(c
1910 .getColumnIndex(ProviderTableMeta.CAPABILITIES_CORE_POLLINTERVAL)));
1911 capability.setFilesSharingApiEnabled(CapabilityBooleanType.fromValue(c.getInt(c
1912 .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_API_ENABLED))));
1913 capability.setFilesSharingPublicEnabled(CapabilityBooleanType.fromValue(c.getInt(c
1914 .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_ENABLED))));
1915 capability.setFilesSharingPublicPasswordEnforced(CapabilityBooleanType.fromValue(c.getInt(c
1916 .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_PASSWORD_ENFORCED))));
1917 capability.setFilesSharingPublicExpireDateEnabled(CapabilityBooleanType.fromValue(c.getInt(c
1918 .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENABLED))));
1919 capability.setFilesSharingPublicExpireDateDays(c.getInt(c
1920 .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_DAYS)));
1921 capability.setFilesSharingPublicExpireDateEnforced(CapabilityBooleanType.fromValue(c.getInt(c
1922 .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENFORCED))));
1923 capability.setFilesSharingPublicSendMail(CapabilityBooleanType.fromValue(c.getInt(c
1924 .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_SEND_MAIL))));
1925 capability.setFilesSharingPublicUpload(CapabilityBooleanType.fromValue(c.getInt(c
1926 .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_UPLOAD))));
1927 capability.setFilesSharingUserSendMail(CapabilityBooleanType.fromValue(c.getInt(c
1928 .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_USER_SEND_MAIL))));
1929 capability.setFilesSharingResharing(CapabilityBooleanType.fromValue(c.getInt(c
1930 .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_RESHARING))));
1931 capability.setFilesSharingFederationOutgoing(CapabilityBooleanType.fromValue(c.getInt(c
1932 .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_OUTGOING))));
1933 capability.setFilesSharingFederationIncoming(CapabilityBooleanType.fromValue(c.getInt(c
1934 .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_INCOMING))));
1935 capability.setFilesBigFileChuncking(CapabilityBooleanType.fromValue(c.getInt(c
1936 .getColumnIndex(ProviderTableMeta.CAPABILITIES_FILES_BIGFILECHUNKING))));
1937 capability.setFilesUndelete(CapabilityBooleanType.fromValue(c.getInt(c
1938 .getColumnIndex(ProviderTableMeta.CAPABILITIES_FILES_UNDELETE))));
1939 capability.setFilesVersioning(CapabilityBooleanType.fromValue(c.getInt(c
1940 .getColumnIndex(ProviderTableMeta.CAPABILITIES_FILES_VERSIONING))));
1941
1942 }
1943 return capability;
1944 }
1945 }