5b5daa721cc6c955b80c6831e6898b0a5984d527
[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 android.accounts.Account;
24 import android.content.ContentProviderClient;
25 import android.content.ContentProviderOperation;
26 import android.content.ContentProviderResult;
27 import android.content.ContentResolver;
28 import android.content.ContentUris;
29 import android.content.ContentValues;
30 import android.content.Intent;
31 import android.content.OperationApplicationException;
32 import android.database.Cursor;
33 import android.net.Uri;
34 import android.os.RemoteException;
35 import android.provider.MediaStore;
36
37 import com.owncloud.android.MainApp;
38 import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
39 import com.owncloud.android.lib.common.utils.Log_OC;
40 import com.owncloud.android.lib.resources.shares.OCShare;
41 import com.owncloud.android.lib.resources.shares.ShareType;
42 import com.owncloud.android.lib.resources.status.CapabilityBooleanType;
43 import com.owncloud.android.lib.resources.status.OCCapability;
44 import com.owncloud.android.utils.FileStorageUtils;
45
46 import java.io.File;
47 import java.io.FileInputStream;
48 import java.io.FileOutputStream;
49 import java.io.IOException;
50 import java.io.InputStream;
51 import java.io.OutputStream;
52 import java.util.ArrayList;
53 import java.util.Collection;
54 import java.util.Collections;
55 import java.util.HashSet;
56 import java.util.Iterator;
57 import java.util.List;
58 import java.util.Set;
59 import java.util.Vector;
60
61 public class FileDataStorageManager {
62
63 public static final int ROOT_PARENT_ID = 0;
64
65 private ContentResolver mContentResolver;
66 private ContentProviderClient mContentProviderClient;
67 private Account mAccount;
68
69 private static String TAG = FileDataStorageManager.class.getSimpleName();
70
71
72 public FileDataStorageManager(Account account, ContentResolver cr) {
73 mContentProviderClient = null;
74 mContentResolver = cr;
75 mAccount = account;
76 }
77
78 public FileDataStorageManager(Account account, ContentProviderClient cp) {
79 mContentProviderClient = cp;
80 mContentResolver = null;
81 mAccount = account;
82 }
83
84
85 public void setAccount(Account account) {
86 mAccount = account;
87 }
88
89 public Account getAccount() {
90 return mAccount;
91 }
92
93 public ContentResolver getContentResolver() {
94 return mContentResolver;
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/*, boolean onlyOnDevice*/) {
146 if (f != null && f.isFolder() && f.getFileId() != -1) {
147 // TODO Enable when "On Device" is recovered ?
148 return getFolderContent(f.getFileId()/*, onlyOnDevice*/);
149
150 } else {
151 return new Vector<OCFile>();
152 }
153 }
154
155
156 public Vector<OCFile> getFolderImages(OCFile folder/*, boolean onlyOnDevice*/) {
157 Vector<OCFile> ret = new Vector<OCFile>();
158 if (folder != null) {
159 // TODO better implementation, filtering in the access to database instead of here
160 // TODO Enable when "On Device" is recovered ?
161 Vector<OCFile> tmp = getFolderContent(folder/*, onlyOnDevice*/);
162 OCFile current = null;
163 for (int i=0; i<tmp.size(); i++) {
164 current = tmp.get(i);
165 if (current.isImage()) {
166 ret.add(current);
167 }
168 }
169 }
170 return ret;
171 }
172
173 public boolean saveFile(OCFile file) {
174 boolean overriden = false;
175 ContentValues cv = new ContentValues();
176 cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
177 cv.put(
178 ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
179 file.getModificationTimestampAtLastSyncForData()
180 );
181 cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
182 cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
183 cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
184 cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
185 cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
186 cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
187 if (!file.isFolder())
188 cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
189 cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
190 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
191 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
192 cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.isFavorite() ? 1 : 0);
193 cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
194 cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, file.isSharedViaLink() ? 1 : 0);
195 cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, file.isSharedWithSharee() ? 1 : 0);
196 cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
197 cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
198 cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
199 cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail());
200 cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading());
201 cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict());
202
203 boolean sameRemotePath = fileExists(file.getRemotePath());
204 if (sameRemotePath ||
205 fileExists(file.getFileId())) { // for renamed files; no more delete and create
206
207 OCFile oldFile;
208 if (sameRemotePath) {
209 oldFile = getFileByPath(file.getRemotePath());
210 file.setFileId(oldFile.getFileId());
211 } else {
212 oldFile = getFileById(file.getFileId());
213 }
214
215 overriden = true;
216 if (getContentResolver() != null) {
217 getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv,
218 ProviderTableMeta._ID + "=?",
219 new String[]{String.valueOf(file.getFileId())});
220 } else {
221 try {
222 getContentProviderClient().update(ProviderTableMeta.CONTENT_URI,
223 cv, ProviderTableMeta._ID + "=?",
224 new String[]{String.valueOf(file.getFileId())});
225 } catch (RemoteException e) {
226 Log_OC.e(TAG,
227 "Fail to insert insert file to database "
228 + e.getMessage());
229 }
230 }
231 } else {
232 Uri result_uri = null;
233 if (getContentResolver() != null) {
234 result_uri = getContentResolver().insert(
235 ProviderTableMeta.CONTENT_URI_FILE, cv);
236 } else {
237 try {
238 result_uri = getContentProviderClient().insert(
239 ProviderTableMeta.CONTENT_URI_FILE, cv);
240 } catch (RemoteException e) {
241 Log_OC.e(TAG,
242 "Fail to insert insert file to database "
243 + e.getMessage());
244 }
245 }
246 if (result_uri != null) {
247 long new_id = Long.parseLong(result_uri.getPathSegments()
248 .get(1));
249 file.setFileId(new_id);
250 }
251 }
252
253 return overriden;
254 }
255
256
257 /**
258 * Inserts or updates the list of files contained in a given folder.
259 * <p/>
260 * CALLER IS THE RESPONSIBLE FOR GRANTING RIGHT UPDATE OF INFORMATION, NOT THIS METHOD.
261 * HERE ONLY DATA CONSISTENCY SHOULD BE GRANTED
262 *
263 * @param folder
264 * @param updatedFiles
265 * @param filesToRemove
266 */
267 public void saveFolder(
268 OCFile folder, Collection<OCFile> updatedFiles, Collection<OCFile> filesToRemove
269 ) {
270
271 Log_OC.d(TAG, "Saving folder " + folder.getRemotePath() + " with " + updatedFiles.size()
272 + " children and " + filesToRemove.size() + " files to remove");
273
274 ArrayList<ContentProviderOperation> operations =
275 new ArrayList<ContentProviderOperation>(updatedFiles.size());
276
277 // prepare operations to insert or update files to save in the given folder
278 for (OCFile file : updatedFiles) {
279 ContentValues cv = new ContentValues();
280 cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
281 cv.put(
282 ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
283 file.getModificationTimestampAtLastSyncForData()
284 );
285 cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
286 cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
287 cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
288 cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
289 //cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
290 cv.put(ProviderTableMeta.FILE_PARENT, folder.getFileId());
291 cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
292 if (!file.isFolder()) {
293 cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
294 }
295 cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
296 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
297 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
298 cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.isFavorite() ? 1 : 0);
299 cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
300 cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, file.isSharedViaLink() ? 1 : 0);
301 cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, file.isSharedWithSharee() ? 1 : 0);
302 cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
303 cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
304 cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
305 cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail());
306 cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading());
307 cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict());
308
309 boolean existsByPath = fileExists(file.getRemotePath());
310 if (existsByPath || fileExists(file.getFileId())) {
311 // updating an existing file
312 operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
313 withValues(cv).
314 withSelection(ProviderTableMeta._ID + "=?",
315 new String[]{String.valueOf(file.getFileId())})
316 .build());
317
318 } else {
319 // adding a new file
320 operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).
321 withValues(cv).build());
322 }
323 }
324
325 // prepare operations to remove files in the given folder
326 String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " +
327 ProviderTableMeta.FILE_PATH + "=?";
328 String [] whereArgs = null;
329 for (OCFile file : filesToRemove) {
330 if (file.getParentId() == folder.getFileId()) {
331 whereArgs = new String[]{mAccount.name, file.getRemotePath()};
332 if (file.isFolder()) {
333 operations.add(ContentProviderOperation.newDelete(
334 ContentUris.withAppendedId(
335 ProviderTableMeta.CONTENT_URI_DIR, file.getFileId()
336 )
337 ).withSelection(where, whereArgs).build());
338
339 File localFolder =
340 new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
341 if (localFolder.exists()) {
342 removeLocalFolder(localFolder);
343 }
344 } else {
345 operations.add(ContentProviderOperation.newDelete(
346 ContentUris.withAppendedId(
347 ProviderTableMeta.CONTENT_URI_FILE, file.getFileId()
348 )
349 ).withSelection(where, whereArgs).build());
350
351 if (file.isDown()) {
352 String path = file.getStoragePath();
353 new File(path).delete();
354 triggerMediaScan(path); // notify MediaScanner about removed file
355 }
356 }
357 }
358 }
359
360 // update metadata of folder
361 ContentValues cv = new ContentValues();
362 cv.put(ProviderTableMeta.FILE_MODIFIED, folder.getModificationTimestamp());
363 cv.put(
364 ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
365 folder.getModificationTimestampAtLastSyncForData()
366 );
367 cv.put(ProviderTableMeta.FILE_CREATION, folder.getCreationTimestamp());
368 cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, 0);
369 cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, folder.getMimetype());
370 cv.put(ProviderTableMeta.FILE_NAME, folder.getFileName());
371 cv.put(ProviderTableMeta.FILE_PARENT, folder.getParentId());
372 cv.put(ProviderTableMeta.FILE_PATH, folder.getRemotePath());
373 cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
374 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, folder.getLastSyncDateForProperties());
375 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, folder.getLastSyncDateForData());
376 cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, folder.isFavorite() ? 1 : 0);
377 cv.put(ProviderTableMeta.FILE_ETAG, folder.getEtag());
378 cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, folder.isSharedViaLink() ? 1 : 0);
379 cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, folder.isSharedWithSharee() ? 1 : 0);
380 cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, folder.getPublicLink());
381 cv.put(ProviderTableMeta.FILE_PERMISSIONS, folder.getPermissions());
382 cv.put(ProviderTableMeta.FILE_REMOTE_ID, folder.getRemoteId());
383
384 operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
385 withValues(cv).
386 withSelection(ProviderTableMeta._ID + "=?",
387 new String[]{String.valueOf(folder.getFileId())})
388 .build());
389
390 // apply operations in batch
391 ContentProviderResult[] results = null;
392 Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
393 try {
394 if (getContentResolver() != null) {
395 results = getContentResolver().applyBatch(MainApp.getAuthority(), operations);
396
397 } else {
398 results = getContentProviderClient().applyBatch(operations);
399 }
400
401 } catch (OperationApplicationException e) {
402 Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
403
404 } catch (RemoteException e) {
405 Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
406 }
407
408 // update new id in file objects for insertions
409 if (results != null) {
410 long newId;
411 Iterator<OCFile> filesIt = updatedFiles.iterator();
412 OCFile file = null;
413 for (int i = 0; i < results.length; i++) {
414 if (filesIt.hasNext()) {
415 file = filesIt.next();
416 } else {
417 file = null;
418 }
419 if (results[i].uri != null) {
420 newId = Long.parseLong(results[i].uri.getPathSegments().get(1));
421 //updatedFiles.get(i).setFileId(newId);
422 if (file != null) {
423 file.setFileId(newId);
424 }
425 }
426 }
427 }
428
429 }
430
431
432 public boolean removeFile(OCFile file, boolean removeDBData, boolean removeLocalCopy) {
433 boolean success = true;
434 if (file != null) {
435 if (file.isFolder()) {
436 success = removeFolder(file, removeDBData, removeLocalCopy);
437
438 } else {
439 if (removeDBData) {
440 //Uri file_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE,
441 // ""+file.getFileId());
442 Uri file_uri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE,
443 file.getFileId());
444 String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " +
445 ProviderTableMeta.FILE_PATH + "=?";
446 String[] whereArgs = new String[]{mAccount.name, file.getRemotePath()};
447 int deleted = 0;
448 if (getContentProviderClient() != null) {
449 try {
450 deleted = getContentProviderClient().delete(file_uri, where, whereArgs);
451 } catch (RemoteException e) {
452 e.printStackTrace();
453 }
454 } else {
455 deleted = getContentResolver().delete(file_uri, where, whereArgs);
456 }
457 success &= (deleted > 0);
458 }
459 String localPath = file.getStoragePath();
460 if (removeLocalCopy && file.isDown() && localPath != null && success) {
461 success = new File(localPath).delete();
462 if (success) {
463 deleteFileInMediaScan(localPath);
464 }
465 if (!removeDBData && success) {
466 // maybe unnecessary, but should be checked TODO remove if unnecessary
467 file.setStoragePath(null);
468 saveFile(file);
469 saveConflict(file, null);
470 }
471 }
472 }
473 }
474 return success;
475 }
476
477
478 public boolean removeFolder(OCFile folder, boolean removeDBData, boolean removeLocalContent) {
479 boolean success = true;
480 if (folder != null && folder.isFolder()) {
481 if (removeDBData && folder.getFileId() != -1) {
482 success = removeFolderInDb(folder);
483 }
484 if (removeLocalContent && success) {
485 success = removeLocalFolder(folder);
486 }
487 }
488 return success;
489 }
490
491 private boolean removeFolderInDb(OCFile folder) {
492 Uri folder_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, "" +
493 folder.getFileId()); // URI for recursive deletion
494 String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " +
495 ProviderTableMeta.FILE_PATH + "=?";
496 String [] whereArgs = new String[]{mAccount.name, folder.getRemotePath()};
497 int deleted = 0;
498 if (getContentProviderClient() != null) {
499 try {
500 deleted = getContentProviderClient().delete(folder_uri, where, whereArgs);
501 } catch (RemoteException e) {
502 e.printStackTrace();
503 }
504 } else {
505 deleted = getContentResolver().delete(folder_uri, where, whereArgs);
506 }
507 return deleted > 0;
508 }
509
510 private boolean removeLocalFolder(OCFile folder) {
511 boolean success = true;
512 String localFolderPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, folder);
513 File localFolder = new File(localFolderPath);
514 if (localFolder.exists()) {
515 // stage 1: remove the local files already registered in the files database
516 // TODO Enable when "On Device" is recovered ?
517 Vector<OCFile> files = getFolderContent(folder.getFileId()/*, false*/);
518 if (files != null) {
519 for (OCFile file : files) {
520 if (file.isFolder()) {
521 success &= removeLocalFolder(file);
522 } else {
523 if (file.isDown()) {
524 File localFile = new File(file.getStoragePath());
525 success &= localFile.delete();
526 if (success) {
527 // notify MediaScanner about removed file
528 deleteFileInMediaScan(file.getStoragePath());
529 file.setStoragePath(null);
530 saveFile(file);
531 }
532 }
533 }
534 }
535 }
536
537 // stage 2: remove the folder itself and any local file inside out of sync;
538 // for instance, after clearing the app cache or reinstalling
539 success &= removeLocalFolder(localFolder);
540 }
541 return success;
542 }
543
544 private boolean removeLocalFolder(File localFolder) {
545 boolean success = true;
546 File[] localFiles = localFolder.listFiles();
547 if (localFiles != null) {
548 for (File localFile : localFiles) {
549 if (localFile.isDirectory()) {
550 success &= removeLocalFolder(localFile);
551 } else {
552 String path = localFile.getAbsolutePath();
553 success &= localFile.delete();
554 }
555 }
556 }
557 success &= localFolder.delete();
558 return success;
559 }
560
561
562 /**
563 * Updates database and file system for a file or folder that was moved to a different location.
564 *
565 * TODO explore better (faster) implementations
566 * TODO throw exceptions up !
567 */
568 public void moveLocalFile(OCFile file, String targetPath, String targetParentPath) {
569
570 if (file != null && file.fileExists() && !OCFile.ROOT_PATH.equals(file.getFileName())) {
571
572 OCFile targetParent = getFileByPath(targetParentPath);
573 if (targetParent == null) {
574 throw new IllegalStateException(
575 "Parent folder of the target path does not exist!!");
576 }
577
578 /// 1. get all the descendants of the moved element in a single QUERY
579 Cursor c = null;
580 if (getContentProviderClient() != null) {
581 try {
582 c = getContentProviderClient().query(
583 ProviderTableMeta.CONTENT_URI,
584 null,
585 ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " +
586 ProviderTableMeta.FILE_PATH + " LIKE ? ",
587 new String[]{
588 mAccount.name,
589 file.getRemotePath() + "%"
590 },
591 ProviderTableMeta.FILE_PATH + " ASC "
592 );
593 } catch (RemoteException e) {
594 Log_OC.e(TAG, e.getMessage());
595 }
596
597 } else {
598 c = getContentResolver().query(
599 ProviderTableMeta.CONTENT_URI,
600 null,
601 ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " +
602 ProviderTableMeta.FILE_PATH + " LIKE ? ",
603 new String[]{
604 mAccount.name,
605 file.getRemotePath() + "%"
606 },
607 ProviderTableMeta.FILE_PATH + " ASC "
608 );
609 }
610
611 /// 2. prepare a batch of update operations to change all the descendants
612 ArrayList<ContentProviderOperation> operations =
613 new ArrayList<ContentProviderOperation>(c.getCount());
614 String defaultSavePath = FileStorageUtils.getSavePath(mAccount.name);
615 List<String> originalPathsToTriggerMediaScan = new ArrayList<String>();
616 List<String> newPathsToTriggerMediaScan = new ArrayList<String>();
617 if (c.moveToFirst()) {
618 int lengthOfOldPath = file.getRemotePath().length();
619 int lengthOfOldStoragePath = defaultSavePath.length() + lengthOfOldPath;
620 do {
621 ContentValues cv = new ContentValues(); // keep construction in the loop
622 OCFile child = createFileInstance(c);
623 cv.put(
624 ProviderTableMeta.FILE_PATH,
625 targetPath + child.getRemotePath().substring(lengthOfOldPath)
626 );
627 if (child.getStoragePath() != null &&
628 child.getStoragePath().startsWith(defaultSavePath)) {
629 // update link to downloaded content - but local move is not done here!
630 String targetLocalPath = defaultSavePath + targetPath +
631 child.getStoragePath().substring(lengthOfOldStoragePath);
632
633 cv.put(ProviderTableMeta.FILE_STORAGE_PATH, targetLocalPath);
634
635 originalPathsToTriggerMediaScan.add(child.getStoragePath());
636 newPathsToTriggerMediaScan.add(targetLocalPath);
637
638 }
639 if (child.getRemotePath().equals(file.getRemotePath())) {
640 cv.put(
641 ProviderTableMeta.FILE_PARENT,
642 targetParent.getFileId()
643 );
644 }
645 operations.add(
646 ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
647 withValues(cv).
648 withSelection(
649 ProviderTableMeta._ID + "=?",
650 new String[]{String.valueOf(child.getFileId())}
651 )
652 .build());
653
654 } while (c.moveToNext());
655 }
656 c.close();
657
658 /// 3. apply updates in batch
659 try {
660 if (getContentResolver() != null) {
661 getContentResolver().applyBatch(MainApp.getAuthority(), operations);
662
663 } else {
664 getContentProviderClient().applyBatch(operations);
665 }
666
667 } catch (Exception e) {
668 Log_OC.e(TAG, "Fail to update " + file.getFileId() + " and descendants in database",
669 e);
670 }
671
672 /// 4. move in local file system
673 String originalLocalPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, file);
674 String targetLocalPath = defaultSavePath + targetPath;
675 File localFile = new File(originalLocalPath);
676 boolean renamed = false;
677 if (localFile.exists()) {
678 File targetFile = new File(targetLocalPath);
679 File targetFolder = targetFile.getParentFile();
680 if (!targetFolder.exists()) {
681 targetFolder.mkdirs();
682 }
683 renamed = localFile.renameTo(targetFile);
684 }
685
686 if (renamed) {
687 Iterator<String> it = originalPathsToTriggerMediaScan.iterator();
688 while (it.hasNext()) {
689 // Notify MediaScanner about removed file
690 deleteFileInMediaScan(it.next());
691 }
692 it = newPathsToTriggerMediaScan.iterator();
693 while (it.hasNext()) {
694 // Notify MediaScanner about new file/folder
695 triggerMediaScan(it.next());
696 }
697 }
698 }
699
700 }
701
702 public void copyLocalFile(OCFile file, String targetPath) {
703
704 if (file != null && file.fileExists() && !OCFile.ROOT_PATH.equals(file.getFileName())) {
705 String localPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, file);
706 File localFile = new File(localPath);
707 boolean copied = false;
708 String defaultSavePath = FileStorageUtils.getSavePath(mAccount.name);
709 if (localFile.exists()) {
710 File targetFile = new File(defaultSavePath + targetPath);
711 File targetFolder = targetFile.getParentFile();
712 if (!targetFolder.exists()) {
713 targetFolder.mkdirs();
714 }
715 copied = copyFile(localFile, targetFile);
716 }
717 Log_OC.d(TAG, "Local file COPIED : " + copied);
718 }
719 }
720
721 private boolean copyFile(File src, File target) {
722 boolean ret = true;
723
724 InputStream in = null;
725 OutputStream out = null;
726
727 try {
728 in = new FileInputStream(src);
729 out = new FileOutputStream(target);
730 byte[] buf = new byte[1024];
731 int len;
732 while ((len = in.read(buf)) > 0) {
733 out.write(buf, 0, len);
734 }
735 } catch (IOException ex) {
736 ret = false;
737 } finally {
738 if (in != null) try {
739 in.close();
740 } catch (IOException e) {
741 e.printStackTrace(System.err);
742 }
743 if (out != null) try {
744 out.close();
745 } catch (IOException e) {
746 e.printStackTrace(System.err);
747 }
748 }
749
750 return ret;
751 }
752
753
754 private Vector<OCFile> getFolderContent(long parentId/*, boolean onlyOnDevice*/) {
755
756 Vector<OCFile> ret = new Vector<OCFile>();
757
758 Uri req_uri = Uri.withAppendedPath(
759 ProviderTableMeta.CONTENT_URI_DIR,
760 String.valueOf(parentId));
761 Cursor c = null;
762
763 if (getContentProviderClient() != null) {
764 try {
765 c = getContentProviderClient().query(req_uri, null,
766 ProviderTableMeta.FILE_PARENT + "=?",
767 new String[]{String.valueOf(parentId)}, null);
768 } catch (RemoteException e) {
769 Log_OC.e(TAG, e.getMessage());
770 return ret;
771 }
772 } else {
773 c = getContentResolver().query(req_uri, null,
774 ProviderTableMeta.FILE_PARENT + "=?",
775 new String[]{String.valueOf(parentId)}, null);
776 }
777
778 if (c.moveToFirst()) {
779 do {
780 OCFile child = createFileInstance(c);
781 // TODO Enable when "On Device" is recovered ?
782 // if (child.isFolder() || !onlyOnDevice || onlyOnDevice && child.isDown()){
783 ret.add(child);
784 // }
785 } while (c.moveToNext());
786 }
787
788 c.close();
789
790 Collections.sort(ret);
791
792 return ret;
793 }
794
795
796 private OCFile createRootDir() {
797 OCFile file = new OCFile(OCFile.ROOT_PATH);
798 file.setMimetype("DIR");
799 file.setParentId(FileDataStorageManager.ROOT_PARENT_ID);
800 saveFile(file);
801 return file;
802 }
803
804 private boolean fileExists(String cmp_key, String value) {
805 Cursor c;
806 if (getContentResolver() != null) {
807 c = getContentResolver()
808 .query(ProviderTableMeta.CONTENT_URI,
809 null,
810 cmp_key + "=? AND "
811 + ProviderTableMeta.FILE_ACCOUNT_OWNER
812 + "=?",
813 new String[]{value, mAccount.name}, null);
814 } else {
815 try {
816 c = getContentProviderClient().query(
817 ProviderTableMeta.CONTENT_URI,
818 null,
819 cmp_key + "=? AND "
820 + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",
821 new String[]{value, mAccount.name}, null);
822 } catch (RemoteException e) {
823 Log_OC.e(TAG,
824 "Couldn't determine file existance, assuming non existance: "
825 + e.getMessage());
826 return false;
827 }
828 }
829 boolean retval = c.moveToFirst();
830 c.close();
831 return retval;
832 }
833
834 private Cursor getCursorForValue(String key, String value) {
835 Cursor c = null;
836 if (getContentResolver() != null) {
837 c = getContentResolver()
838 .query(ProviderTableMeta.CONTENT_URI,
839 null,
840 key + "=? AND "
841 + ProviderTableMeta.FILE_ACCOUNT_OWNER
842 + "=?",
843 new String[]{value, mAccount.name}, null);
844 } else {
845 try {
846 c = getContentProviderClient().query(
847 ProviderTableMeta.CONTENT_URI,
848 null,
849 key + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER
850 + "=?", new String[]{value, mAccount.name},
851 null);
852 } catch (RemoteException e) {
853 Log_OC.e(TAG, "Could not get file details: " + e.getMessage());
854 c = null;
855 }
856 }
857 return c;
858 }
859
860
861 private OCFile createFileInstance(Cursor c) {
862 OCFile file = null;
863 if (c != null) {
864 file = new OCFile(c.getString(c
865 .getColumnIndex(ProviderTableMeta.FILE_PATH)));
866 file.setFileId(c.getLong(c.getColumnIndex(ProviderTableMeta._ID)));
867 file.setParentId(c.getLong(c
868 .getColumnIndex(ProviderTableMeta.FILE_PARENT)));
869 file.setMimetype(c.getString(c
870 .getColumnIndex(ProviderTableMeta.FILE_CONTENT_TYPE)));
871 if (!file.isFolder()) {
872 file.setStoragePath(c.getString(c
873 .getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH)));
874 if (file.getStoragePath() == null) {
875 // try to find existing file and bind it with current account;
876 // with the current update of SynchronizeFolderOperation, this won't be
877 // necessary anymore after a full synchronization of the account
878 File f = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
879 if (f.exists()) {
880 file.setStoragePath(f.getAbsolutePath());
881 file.setLastSyncDateForData(f.lastModified());
882 }
883 }
884 }
885 file.setFileLength(c.getLong(c
886 .getColumnIndex(ProviderTableMeta.FILE_CONTENT_LENGTH)));
887 file.setCreationTimestamp(c.getLong(c
888 .getColumnIndex(ProviderTableMeta.FILE_CREATION)));
889 file.setModificationTimestamp(c.getLong(c
890 .getColumnIndex(ProviderTableMeta.FILE_MODIFIED)));
891 file.setModificationTimestampAtLastSyncForData(c.getLong(c
892 .getColumnIndex(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA)));
893 file.setLastSyncDateForProperties(c.getLong(c
894 .getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE)));
895 file.setLastSyncDateForData(c.getLong(c.
896 getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA)));
897 file.setFavorite(c.getInt(
898 c.getColumnIndex(ProviderTableMeta.FILE_KEEP_IN_SYNC)) == 1 ? true : false);
899 file.setEtag(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG)));
900 file.setShareViaLink(c.getInt(
901 c.getColumnIndex(ProviderTableMeta.FILE_SHARED_VIA_LINK)) == 1 ? true : false);
902 file.setShareWithSharee(c.getInt(
903 c.getColumnIndex(ProviderTableMeta.FILE_SHARED_WITH_SHAREE)) == 1 ? true : false);
904 file.setPublicLink(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PUBLIC_LINK)));
905 file.setPermissions(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PERMISSIONS)));
906 file.setRemoteId(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_REMOTE_ID)));
907 file.setNeedsUpdateThumbnail(c.getInt(
908 c.getColumnIndex(ProviderTableMeta.FILE_UPDATE_THUMBNAIL)) == 1 ? true : false);
909 file.setDownloading(c.getInt(
910 c.getColumnIndex(ProviderTableMeta.FILE_IS_DOWNLOADING)) == 1 ? true : false);
911 file.setEtagInConflict(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG_IN_CONFLICT)));
912
913 }
914 return file;
915 }
916
917 // Methods for Shares
918 public boolean saveShare(OCShare share) {
919 boolean overriden = false;
920 ContentValues cv = new ContentValues();
921 cv.put(ProviderTableMeta.OCSHARES_FILE_SOURCE, share.getFileSource());
922 cv.put(ProviderTableMeta.OCSHARES_ITEM_SOURCE, share.getItemSource());
923 cv.put(ProviderTableMeta.OCSHARES_SHARE_TYPE, share.getShareType().getValue());
924 cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH, share.getShareWith());
925 cv.put(ProviderTableMeta.OCSHARES_PATH, share.getPath());
926 cv.put(ProviderTableMeta.OCSHARES_PERMISSIONS, share.getPermissions());
927 cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
928 cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
929 cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
930 cv.put(
931 ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME,
932 share.getSharedWithDisplayName()
933 );
934 cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
935 cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
936 cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getRemoteId());
937 cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, mAccount.name);
938
939 if (shareExists(share.getRemoteId())) {// for renamed files; no more delete and create
940 overriden = true;
941 if (getContentResolver() != null) {
942 getContentResolver().update(ProviderTableMeta.CONTENT_URI_SHARE, cv,
943 ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?",
944 new String[]{String.valueOf(share.getRemoteId())});
945 } else {
946 try {
947 getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_SHARE,
948 cv, ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?",
949 new String[]{String.valueOf(share.getRemoteId())});
950 } catch (RemoteException e) {
951 Log_OC.e(TAG,
952 "Fail to insert insert file to database "
953 + e.getMessage());
954 }
955 }
956 } else {
957 Uri result_uri = null;
958 if (getContentResolver() != null) {
959 result_uri = getContentResolver().insert(
960 ProviderTableMeta.CONTENT_URI_SHARE, cv);
961 } else {
962 try {
963 result_uri = getContentProviderClient().insert(
964 ProviderTableMeta.CONTENT_URI_SHARE, cv);
965 } catch (RemoteException e) {
966 Log_OC.e(TAG,
967 "Fail to insert insert file to database "
968 + e.getMessage());
969 }
970 }
971 if (result_uri != null) {
972 long new_id = Long.parseLong(result_uri.getPathSegments()
973 .get(1));
974 share.setId(new_id);
975 }
976 }
977
978 return overriden;
979 }
980
981
982 /**
983 * Get first share bound to a file with a known path and given {@link ShareType}.
984 *
985 * @param path Path of the file.
986 * @param type Type of the share to get
987 * @param shareWith Target of the share. Ignored in type is {@link ShareType#PUBLIC_LINK}
988 * @return First {@OCShare} instance found in DB bound to the file in 'path'
989 */
990 public OCShare getFirstShareByPathAndType(String path, ShareType type, String shareWith) {
991 Cursor c = null;
992 if (shareWith == null) {
993 shareWith = "";
994 }
995
996 String selection = ProviderTableMeta.OCSHARES_PATH + "=? AND "
997 + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? AND "
998 + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?" ;
999 if (!ShareType.PUBLIC_LINK.equals(type)) {
1000 selection += " AND " + ProviderTableMeta.OCSHARES_SHARE_WITH + "=?";
1001 }
1002
1003 String [] selectionArgs;
1004 if (ShareType.PUBLIC_LINK.equals(type)) {
1005 selectionArgs = new String[]{
1006 path,
1007 Integer.toString(type.getValue()),
1008 mAccount.name
1009 };
1010 } else {
1011 selectionArgs = new String[]{
1012 path,
1013 Integer.toString(type.getValue()),
1014 mAccount.name,
1015 shareWith
1016 };
1017 }
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.getRemoteId());
1218 cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, mAccount.name);
1219
1220 if (shareExists(share.getRemoteId())) {
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.getRemoteId())})
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.getRemoteId());
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 }