FileDataStorageManager.java 63 KB

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