FileDataStorageManager.java 63 KB

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