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