OCFile.java 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053
  1. /*
  2. * Nextcloud - Android Client
  3. *
  4. * SPDX-FileCopyrightText: 2023 Alper Ozturk <alper_ozturk@proton.me>
  5. * SPDX-FileCopyrightText: 2022 Álvaro Brey Vilas <alvaro@alvarobrey.com>
  6. * SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
  7. * SPDX-FileCopyrightText: 2018 Andy Scherzinger <info@andy-scherzinger.de>
  8. * SPDX-FileCopyrightText: 2018 Mario Danic <mario@lovelyhq.com>
  9. * SPDX-FileCopyrightText: 2016 ownCloud Inc.
  10. * SPDX-FileCopyrightText: 2012-2016 David A. Velasco <dvelasco@solidgear.es>
  11. * SPDX-FileCopyrightText: 2012 Bartosz Przybylski <bart.p.pl@gmail.com>
  12. * SPDX-License-Identifier: GPL-2.0-only AND AGPL-3.0-or-later
  13. */
  14. package com.owncloud.android.datamodel;
  15. import android.content.ContentResolver;
  16. import android.content.Context;
  17. import android.net.Uri;
  18. import android.os.Parcel;
  19. import android.os.Parcelable;
  20. import android.text.TextUtils;
  21. import com.owncloud.android.R;
  22. import com.owncloud.android.lib.common.network.WebdavEntry;
  23. import com.owncloud.android.lib.common.network.WebdavUtils;
  24. import com.owncloud.android.lib.common.utils.Log_OC;
  25. import com.owncloud.android.lib.resources.files.model.FileLockType;
  26. import com.owncloud.android.lib.resources.files.model.GeoLocation;
  27. import com.owncloud.android.lib.resources.files.model.ImageDimension;
  28. import com.owncloud.android.lib.resources.files.model.ServerFileInterface;
  29. import com.owncloud.android.lib.resources.shares.ShareeUser;
  30. import com.owncloud.android.utils.MimeType;
  31. import java.io.File;
  32. import java.util.ArrayList;
  33. import java.util.List;
  34. import androidx.annotation.NonNull;
  35. import androidx.annotation.Nullable;
  36. import androidx.annotation.VisibleForTesting;
  37. import androidx.core.content.FileProvider;
  38. import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
  39. import third_parties.daveKoeller.AlphanumComparator;
  40. public class OCFile implements Parcelable, Comparable<OCFile>, ServerFileInterface {
  41. private final static String PERMISSION_SHARED_WITH_ME = "S";
  42. @VisibleForTesting
  43. public final static String PERMISSION_CAN_RESHARE = "R";
  44. private final static String PERMISSION_CAN_WRITE = "CK";
  45. private final static String PERMISSION_GROUPFOLDER = "M";
  46. public static final String PATH_SEPARATOR = "/";
  47. public static final String ROOT_PATH = PATH_SEPARATOR;
  48. private static final String TAG = OCFile.class.getSimpleName();
  49. private long fileId; // android internal ID of the file
  50. private long parentId;
  51. private long fileLength;
  52. private long creationTimestamp; // UNIX timestamp of the time the file was created
  53. private long modificationTimestamp; // UNIX timestamp of the file modification time
  54. private long uploadTimestamp;
  55. /**
  56. * UNIX timestamp of the modification time, corresponding to the value returned by the server in the last
  57. * synchronization of THE CONTENTS of this file.
  58. */
  59. private long modificationTimestampAtLastSyncForData;
  60. private long firstShareTimestamp; // UNIX timestamp of the first share time
  61. private String remotePath;
  62. private String decryptedRemotePath;
  63. private String localPath;
  64. private String mimeType;
  65. private boolean needsUpdatingWhileSaving;
  66. private long lastSyncDateForProperties;
  67. private long lastSyncDateForData;
  68. private boolean previewAvailable;
  69. private String livePhoto;
  70. public OCFile livePhotoVideo;
  71. private String etag;
  72. private String etagOnServer;
  73. private boolean sharedViaLink;
  74. private String permissions;
  75. private long localId; // unique fileId for the file within the instance
  76. private String remoteId; // The fileid namespaced by the instance fileId, globally unique
  77. private boolean updateThumbnailNeeded;
  78. private boolean downloading;
  79. private String etagInConflict; // Only saves file etag in the server, when there is a conflict
  80. private boolean sharedWithSharee;
  81. private boolean favorite;
  82. private boolean hidden;
  83. private boolean encrypted;
  84. private WebdavEntry.MountType mountType;
  85. private int unreadCommentsCount;
  86. private String ownerId;
  87. private String ownerDisplayName;
  88. String note;
  89. private List<ShareeUser> sharees;
  90. private String richWorkspace;
  91. private boolean locked;
  92. @Nullable
  93. private FileLockType lockType;
  94. @Nullable
  95. private String lockOwnerId;
  96. @Nullable
  97. private String lockOwnerDisplayName;
  98. @Nullable
  99. private String lockOwnerEditor;
  100. private long lockTimestamp;
  101. private long lockTimeout;
  102. @Nullable
  103. private String lockToken;
  104. @Nullable
  105. private ImageDimension imageDimension;
  106. private long e2eCounter = -1;
  107. @Nullable
  108. private GeoLocation geolocation;
  109. private List<String> tags = new ArrayList<>();
  110. /**
  111. * URI to the local path of the file contents, if stored in the device; cached after first call to
  112. * {@link #getStorageUri()}
  113. */
  114. private Uri localUri;
  115. /**
  116. * Exportable URI to the local path of the file contents, if stored in the device.
  117. * <p>
  118. * Cached after first call, until changed.
  119. */
  120. private Uri exposedFileUri;
  121. /**
  122. * Create new {@link OCFile} with given path.
  123. * <p>
  124. * The path received must be URL-decoded. Path separator must be OCFile.PATH_SEPARATOR, and it must be the first character in 'path'.
  125. *
  126. * @param path The remote path of the file.
  127. */
  128. public OCFile(String path) {
  129. resetData();
  130. needsUpdatingWhileSaving = false;
  131. if (TextUtils.isEmpty(path) || !path.startsWith(PATH_SEPARATOR)) {
  132. throw new IllegalArgumentException("Trying to create a OCFile with a non valid remote path: " + path);
  133. }
  134. remotePath = path;
  135. }
  136. /**
  137. * Reconstruct from parcel
  138. *
  139. * @param source The source parcel
  140. */
  141. private OCFile(Parcel source) {
  142. fileId = source.readLong();
  143. parentId = source.readLong();
  144. fileLength = source.readLong();
  145. creationTimestamp = source.readLong();
  146. modificationTimestamp = source.readLong();
  147. modificationTimestampAtLastSyncForData = source.readLong();
  148. remotePath = source.readString();
  149. decryptedRemotePath = source.readString();
  150. localPath = source.readString();
  151. mimeType = source.readString();
  152. needsUpdatingWhileSaving = source.readInt() == 0;
  153. lastSyncDateForProperties = source.readLong();
  154. lastSyncDateForData = source.readLong();
  155. etag = source.readString();
  156. etagOnServer = source.readString();
  157. sharedViaLink = source.readInt() == 1;
  158. permissions = source.readString();
  159. localId = source.readLong();
  160. remoteId = source.readString();
  161. updateThumbnailNeeded = source.readInt() == 1;
  162. downloading = source.readInt() == 1;
  163. etagInConflict = source.readString();
  164. sharedWithSharee = source.readInt() == 1;
  165. favorite = source.readInt() == 1;
  166. hidden = source.readInt() == 1;
  167. encrypted = source.readInt() == 1;
  168. ownerId = source.readString();
  169. ownerDisplayName = source.readString();
  170. mountType = (WebdavEntry.MountType) source.readSerializable();
  171. richWorkspace = source.readString();
  172. previewAvailable = source.readInt() == 1;
  173. firstShareTimestamp = source.readLong();
  174. locked = source.readInt() == 1;
  175. lockType = FileLockType.fromValue(source.readInt());
  176. lockOwnerId = source.readString();
  177. lockOwnerDisplayName = source.readString();
  178. lockOwnerEditor = source.readString();
  179. lockTimestamp = source.readLong();
  180. lockTimeout = source.readLong();
  181. lockToken = source.readString();
  182. livePhoto = source.readString();
  183. }
  184. @Override
  185. public void writeToParcel(Parcel dest, int flags) {
  186. dest.writeLong(fileId);
  187. dest.writeLong(parentId);
  188. dest.writeLong(fileLength);
  189. dest.writeLong(creationTimestamp);
  190. dest.writeLong(modificationTimestamp);
  191. dest.writeLong(modificationTimestampAtLastSyncForData);
  192. dest.writeString(remotePath);
  193. dest.writeString(decryptedRemotePath);
  194. dest.writeString(localPath);
  195. dest.writeString(mimeType);
  196. dest.writeInt(needsUpdatingWhileSaving ? 1 : 0);
  197. dest.writeLong(lastSyncDateForProperties);
  198. dest.writeLong(lastSyncDateForData);
  199. dest.writeString(etag);
  200. dest.writeString(etagOnServer);
  201. dest.writeInt(sharedViaLink ? 1 : 0);
  202. dest.writeString(permissions);
  203. dest.writeLong(localId);
  204. dest.writeString(remoteId);
  205. dest.writeInt(updateThumbnailNeeded ? 1 : 0);
  206. dest.writeInt(downloading ? 1 : 0);
  207. dest.writeString(etagInConflict);
  208. dest.writeInt(sharedWithSharee ? 1 : 0);
  209. dest.writeInt(favorite ? 1 : 0);
  210. dest.writeInt(hidden ? 1 : 0);
  211. dest.writeInt(encrypted ? 1 : 0);
  212. dest.writeString(ownerId);
  213. dest.writeString(ownerDisplayName);
  214. dest.writeSerializable(mountType);
  215. dest.writeString(richWorkspace);
  216. dest.writeInt(previewAvailable ? 1 : 0);
  217. dest.writeLong(firstShareTimestamp);
  218. dest.writeInt(locked ? 1 : 0);
  219. dest.writeInt(lockType != null ? lockType.getValue() : -1);
  220. dest.writeString(lockOwnerId);
  221. dest.writeString(lockOwnerDisplayName);
  222. dest.writeString(lockOwnerEditor);
  223. dest.writeLong(lockTimestamp);
  224. dest.writeLong(lockTimeout);
  225. dest.writeString(lockToken);
  226. dest.writeString(livePhoto);
  227. }
  228. public String getLinkedFileIdForLivePhoto() {
  229. return livePhoto;
  230. }
  231. public void setLivePhoto(String livePhoto) {
  232. this.livePhoto = livePhoto;
  233. }
  234. public void setDecryptedRemotePath(String path) {
  235. decryptedRemotePath = path;
  236. }
  237. /**
  238. * Use decrypted remote path for every local file operation Use encrypted remote path for every dav related
  239. * operation
  240. */
  241. public String getDecryptedRemotePath() {
  242. // Fallback
  243. // TODO test without, on a new created folder
  244. if (!isEncrypted() && decryptedRemotePath == null) {
  245. decryptedRemotePath = remotePath;
  246. }
  247. if (isFolder()) {
  248. if (decryptedRemotePath.endsWith(PATH_SEPARATOR)) {
  249. return decryptedRemotePath;
  250. } else {
  251. return decryptedRemotePath + PATH_SEPARATOR;
  252. }
  253. } else {
  254. if (decryptedRemotePath == null) {
  255. // last fallback
  256. return remotePath;
  257. } else {
  258. return decryptedRemotePath;
  259. }
  260. }
  261. }
  262. /**
  263. * Returns the remote path of the file on Nextcloud
  264. * (this might be an encrypted file path, if E2E is used)
  265. * <p>
  266. * Use decrypted remote path for every local file operation.
  267. * Use remote path for every dav related operation
  268. *
  269. * @return The remote path to the file
  270. */
  271. public String getRemotePath() {
  272. if (isFolder()) {
  273. if (remotePath.endsWith(PATH_SEPARATOR)) {
  274. return remotePath;
  275. } else {
  276. return remotePath + PATH_SEPARATOR;
  277. }
  278. } else {
  279. return remotePath;
  280. }
  281. }
  282. /**
  283. * Can be used to check, whether or not this file exists in the database already
  284. *
  285. * @return true, if the file exists in the database
  286. */
  287. public boolean fileExists() {
  288. return fileId != -1;
  289. }
  290. /**
  291. * Use this to find out if this file is a folder.
  292. *
  293. * @return true if it is a folder
  294. */
  295. public boolean isFolder() {
  296. return MimeType.DIRECTORY.equals(mimeType) || MimeType.WEBDAV_FOLDER.equals(mimeType);
  297. }
  298. /**
  299. * Sets mimetype to folder and returns this file
  300. * Only for testing
  301. *
  302. * @return OCFile this file
  303. */
  304. public OCFile setFolder() {
  305. setMimeType(MimeType.DIRECTORY);
  306. return this;
  307. }
  308. /**
  309. * Use this to check if this file is available locally
  310. *
  311. * @return true if it is
  312. */
  313. public boolean isDown() {
  314. return !isFolder() && existsOnDevice();
  315. }
  316. /**
  317. * Use this to check if this file or folder is available locally
  318. *
  319. * @return true if it is
  320. */
  321. public boolean existsOnDevice() {
  322. if (!TextUtils.isEmpty(localPath)) {
  323. return new File(localPath).exists();
  324. }
  325. return false;
  326. }
  327. /**
  328. * The path, where the file is stored locally
  329. *
  330. * @return The local path to the file
  331. */
  332. public String getStoragePath() {
  333. return localPath;
  334. }
  335. /**
  336. * The URI to the file contents, if stored locally
  337. *
  338. * @return A URI to the local copy of the file, or NULL if not stored in the device
  339. */
  340. public Uri getStorageUri() {
  341. if (TextUtils.isEmpty(localPath)) {
  342. return null;
  343. }
  344. if (localUri == null) {
  345. Uri.Builder builder = new Uri.Builder();
  346. builder.scheme(ContentResolver.SCHEME_FILE);
  347. builder.path(localPath);
  348. localUri = builder.build();
  349. }
  350. return localUri;
  351. }
  352. public Uri getLegacyExposedFileUri() {
  353. if (TextUtils.isEmpty(localPath)) {
  354. return null;
  355. }
  356. if (exposedFileUri == null) {
  357. return Uri.parse(ContentResolver.SCHEME_FILE + "://" + WebdavUtils.encodePath(localPath));
  358. }
  359. return exposedFileUri;
  360. }
  361. /*
  362. Partly disabled because not all apps understand paths that we get via this method for now
  363. */
  364. public Uri getExposedFileUri(Context context) {
  365. if (TextUtils.isEmpty(localPath)) {
  366. return null;
  367. }
  368. if (exposedFileUri == null) {
  369. try {
  370. exposedFileUri = FileProvider.getUriForFile(
  371. context,
  372. context.getString(R.string.file_provider_authority),
  373. new File(localPath));
  374. } catch (IllegalArgumentException ex) {
  375. // Could not share file using FileProvider URI scheme.
  376. // Fall back to legacy URI parsing.
  377. getLegacyExposedFileUri();
  378. }
  379. }
  380. return exposedFileUri;
  381. }
  382. /**
  383. * Can be used to set the path where the file is stored
  384. *
  385. * @param storage_path to set
  386. */
  387. public void setStoragePath(String storage_path) {
  388. if (storage_path == null) {
  389. localPath = null;
  390. } else {
  391. localPath = storage_path.replaceAll("//", "/");
  392. if (isFolder() && !localPath.endsWith("/")) {
  393. localPath = localPath + "/";
  394. }
  395. }
  396. localUri = null;
  397. exposedFileUri = null;
  398. }
  399. /**
  400. * Returns the decrypted filename and "/" for the root directory
  401. *
  402. * @return The name of the file
  403. */
  404. public String getFileName() {
  405. return getDecryptedFileName();
  406. }
  407. /**
  408. * Returns the decrypted filename and "/" for the root directory
  409. *
  410. * @return The name of the file
  411. */
  412. public String getDecryptedFileName() {
  413. File f = new File(getDecryptedRemotePath());
  414. return f.getName().length() == 0 ? ROOT_PATH : f.getName();
  415. }
  416. /**
  417. * Returns the encrypted filename and "/" for the root directory
  418. *
  419. * @return The name of the file
  420. */
  421. public String getEncryptedFileName() {
  422. File f = new File(remotePath);
  423. return f.getName().length() == 0 ? ROOT_PATH : f.getName();
  424. }
  425. /**
  426. * Sets the name of the file
  427. * <p/>
  428. * Does nothing if the new name is null, empty or includes "/" ; or if the file is the root
  429. * directory
  430. */
  431. public void setFileName(String name) {
  432. Log_OC.d(TAG, "OCFile name changing from " + remotePath);
  433. if (!TextUtils.isEmpty(name) && !name.contains(PATH_SEPARATOR) && !ROOT_PATH.equals(remotePath)) {
  434. String parent = new File(this.getRemotePath()).getParent();
  435. if (parent != null) {
  436. parent = parent.endsWith(PATH_SEPARATOR) ? parent : parent + PATH_SEPARATOR;
  437. remotePath = parent + name;
  438. if (isFolder()) {
  439. remotePath += PATH_SEPARATOR;
  440. }
  441. Log_OC.d(TAG, "OCFile name changed to " + remotePath);
  442. }
  443. }
  444. }
  445. /**
  446. * Used internally. Reset all file properties
  447. */
  448. private void resetData() {
  449. fileId = -1;
  450. remotePath = null;
  451. decryptedRemotePath = null;
  452. parentId = 0;
  453. localPath = null;
  454. mimeType = null;
  455. fileLength = 0;
  456. creationTimestamp = 0;
  457. modificationTimestamp = 0;
  458. modificationTimestampAtLastSyncForData = 0;
  459. lastSyncDateForProperties = 0;
  460. lastSyncDateForData = 0;
  461. needsUpdatingWhileSaving = false;
  462. etag = null;
  463. etagOnServer = null;
  464. sharedViaLink = false;
  465. permissions = null;
  466. localId = -1;
  467. remoteId = null;
  468. updateThumbnailNeeded = false;
  469. downloading = false;
  470. etagInConflict = null;
  471. sharedWithSharee = false;
  472. favorite = false;
  473. hidden = false;
  474. encrypted = false;
  475. mountType = WebdavEntry.MountType.INTERNAL;
  476. richWorkspace = "";
  477. firstShareTimestamp = 0;
  478. locked = false;
  479. lockType = null;
  480. lockOwnerId = null;
  481. lockOwnerDisplayName = null;
  482. lockOwnerEditor = null;
  483. lockTimestamp = 0;
  484. lockTimeout = 0;
  485. lockToken = null;
  486. livePhoto = null;
  487. imageDimension = null;
  488. }
  489. /**
  490. * get remote path of parent file
  491. *
  492. * @return remote path
  493. */
  494. public String getParentRemotePath() {
  495. String parentPath = new File(this.getRemotePath()).getParent();
  496. if (parentPath != null) {
  497. return parentPath.endsWith(PATH_SEPARATOR) ? parentPath : parentPath + PATH_SEPARATOR;
  498. } else {
  499. return null;
  500. }
  501. }
  502. @Override
  503. public int describeContents() {
  504. return super.hashCode();
  505. }
  506. @Override
  507. public int compareTo(@NonNull OCFile another) {
  508. if (isFolder() && another.isFolder()) {
  509. return AlphanumComparator.compare(this, another);
  510. } else if (isFolder()) {
  511. return -1;
  512. } else if (another.isFolder()) {
  513. return 1;
  514. }
  515. return AlphanumComparator.compare(this, another);
  516. }
  517. @Override
  518. public boolean equals(Object o) {
  519. if (this == o) {
  520. return true;
  521. }
  522. if (o == null || getClass() != o.getClass()) {
  523. return false;
  524. }
  525. OCFile ocFile = (OCFile) o;
  526. return fileId == ocFile.fileId && parentId == ocFile.parentId;
  527. }
  528. @Override
  529. public int hashCode() {
  530. return 31 * (int) (fileId ^ (fileId >>> 32)) + (int) (parentId ^ (parentId >>> 32));
  531. }
  532. @NonNull
  533. @Override
  534. public String toString() {
  535. String asString = "[id=%s, name=%s, mime=%s, downloaded=%s, local=%s, remote=%s, " +
  536. "parentId=%s, etag=%s, favourite=%s]";
  537. return String.format(asString,
  538. fileId,
  539. getFileName(),
  540. mimeType,
  541. isDown(),
  542. localPath,
  543. remotePath,
  544. parentId,
  545. etag,
  546. favorite);
  547. }
  548. public void setEtag(String etag) {
  549. this.etag = etag != null ? etag : "";
  550. }
  551. public void setEtagOnServer(String etag) {
  552. this.etagOnServer = etag != null ? etag : "";
  553. }
  554. public long getLocalModificationTimestamp() {
  555. if (!TextUtils.isEmpty(localPath)) {
  556. File f = new File(localPath);
  557. return f.lastModified();
  558. }
  559. return 0;
  560. }
  561. /**
  562. * @return 'True' if the file is hidden
  563. */
  564. public boolean isHidden() {
  565. return !TextUtils.isEmpty(getFileName()) && getFileName().charAt(0) == '.';
  566. }
  567. /**
  568. * unique fileId for the file within the instance
  569. */
  570. @SuppressFBWarnings("STT")
  571. public long getLocalId() {
  572. if (localId > 0) {
  573. return localId;
  574. } else if (remoteId != null && remoteId.length() > 8) {
  575. return Long.parseLong(remoteId.substring(0, 8).replaceAll("^0*", ""));
  576. } else {
  577. return -1;
  578. }
  579. }
  580. public boolean isInConflict() {
  581. return !TextUtils.isEmpty(etagInConflict);
  582. }
  583. public boolean isSharedWithMe() {
  584. String permissions = getPermissions();
  585. return permissions != null && permissions.contains(PERMISSION_SHARED_WITH_ME);
  586. }
  587. public boolean canReshare() {
  588. String permissions = getPermissions();
  589. return permissions != null && permissions.contains(PERMISSION_CAN_RESHARE);
  590. }
  591. public boolean canWrite() {
  592. String permissions = getPermissions();
  593. return permissions != null && permissions.contains(PERMISSION_CAN_WRITE);
  594. }
  595. public boolean isGroupFolder() {
  596. String permissions = getPermissions();
  597. return permissions != null && permissions.contains(PERMISSION_GROUPFOLDER);
  598. }
  599. public Integer getFileOverlayIconId(boolean isAutoUploadFolder) {
  600. if (WebdavEntry.MountType.GROUP == mountType || isGroupFolder()) {
  601. return R.drawable.ic_folder_overlay_account_group;
  602. } else if (sharedViaLink && !encrypted) {
  603. return R.drawable.ic_folder_overlay_link;
  604. } else if (isSharedWithMe() || sharedWithSharee) {
  605. return R.drawable.ic_folder_overlay_share;
  606. } else if (encrypted) {
  607. return R.drawable.ic_folder_overlay_key;
  608. } else if (WebdavEntry.MountType.EXTERNAL == mountType) {
  609. return R.drawable.ic_folder_overlay_external;
  610. } else if (locked) {
  611. return R.drawable.ic_folder_overlay_lock;
  612. } else if (isAutoUploadFolder) {
  613. return R.drawable.ic_folder_overlay_upload;
  614. } else {
  615. return null;
  616. }
  617. }
  618. public static final Parcelable.Creator<OCFile> CREATOR = new Parcelable.Creator<OCFile>() {
  619. @Override
  620. public OCFile createFromParcel(Parcel source) {
  621. return new OCFile(source);
  622. }
  623. @Override
  624. public OCFile[] newArray(int size) {
  625. return new OCFile[size];
  626. }
  627. };
  628. /**
  629. * Android's internal ID of the file
  630. */
  631. public long getFileId() {
  632. return this.fileId;
  633. }
  634. public long getParentId() {
  635. return this.parentId;
  636. }
  637. public long getFileLength() {
  638. return this.fileLength;
  639. }
  640. public long getCreationTimestamp() {
  641. return this.creationTimestamp;
  642. }
  643. /**
  644. * @return unix timestamp in milliseconds
  645. */
  646. public long getModificationTimestamp() {
  647. return this.modificationTimestamp;
  648. }
  649. public long getUploadTimestamp() {
  650. return this.uploadTimestamp;
  651. }
  652. public long getModificationTimestampAtLastSyncForData() {
  653. return this.modificationTimestampAtLastSyncForData;
  654. }
  655. public String getMimeType() {
  656. return this.mimeType;
  657. }
  658. public boolean isNeedsUpdatingWhileSaving() {
  659. return this.needsUpdatingWhileSaving;
  660. }
  661. public long getLastSyncDateForProperties() {
  662. return this.lastSyncDateForProperties;
  663. }
  664. public long getLastSyncDateForData() {
  665. return this.lastSyncDateForData;
  666. }
  667. public boolean isPreviewAvailable() {
  668. return this.previewAvailable;
  669. }
  670. public String getEtag() {
  671. return this.etag;
  672. }
  673. public String getEtagOnServer() {
  674. return this.etagOnServer;
  675. }
  676. public boolean isSharedViaLink() {
  677. return this.sharedViaLink;
  678. }
  679. public String getPermissions() {
  680. return this.permissions;
  681. }
  682. public String getRemoteId() {
  683. return this.remoteId;
  684. }
  685. public boolean isUpdateThumbnailNeeded() {
  686. return this.updateThumbnailNeeded;
  687. }
  688. public boolean isDownloading() {
  689. return this.downloading;
  690. }
  691. public String getEtagInConflict() {
  692. return this.etagInConflict;
  693. }
  694. public boolean isSharedWithSharee() {
  695. return this.sharedWithSharee;
  696. }
  697. public boolean isFavorite() {
  698. return this.favorite;
  699. }
  700. public boolean shouldHide() {
  701. return this.hidden;
  702. }
  703. public boolean isEncrypted() {
  704. return this.encrypted;
  705. }
  706. public WebdavEntry.MountType getMountType() {
  707. return this.mountType;
  708. }
  709. public int getUnreadCommentsCount() {
  710. return this.unreadCommentsCount;
  711. }
  712. public String getOwnerId() {
  713. return this.ownerId;
  714. }
  715. public String getOwnerDisplayName() {
  716. return this.ownerDisplayName;
  717. }
  718. public String getNote() {
  719. return this.note;
  720. }
  721. public List<ShareeUser> getSharees() {
  722. return this.sharees;
  723. }
  724. public String getRichWorkspace() {
  725. return this.richWorkspace;
  726. }
  727. public void setFileId(long fileId) {
  728. this.fileId = fileId;
  729. }
  730. public void setLocalId(long localId) {
  731. this.localId = localId;
  732. }
  733. public void setParentId(long parentId) {
  734. this.parentId = parentId;
  735. }
  736. public void setFileLength(long fileLength) {
  737. this.fileLength = fileLength;
  738. }
  739. public void setCreationTimestamp(long creationTimestamp) {
  740. this.creationTimestamp = creationTimestamp;
  741. }
  742. public void setModificationTimestamp(long modificationTimestamp) {
  743. this.modificationTimestamp = modificationTimestamp;
  744. }
  745. public void setModificationTimestampAtLastSyncForData(long modificationTimestampAtLastSyncForData) {
  746. this.modificationTimestampAtLastSyncForData = modificationTimestampAtLastSyncForData;
  747. }
  748. public void setRemotePath(String remotePath) {
  749. this.remotePath = remotePath;
  750. }
  751. public void setMimeType(String mimeType) {
  752. this.mimeType = mimeType;
  753. }
  754. public void setLastSyncDateForProperties(long lastSyncDateForProperties) {
  755. this.lastSyncDateForProperties = lastSyncDateForProperties;
  756. }
  757. public void setLastSyncDateForData(long lastSyncDateForData) {
  758. this.lastSyncDateForData = lastSyncDateForData;
  759. }
  760. public void setPreviewAvailable(boolean previewAvailable) {
  761. this.previewAvailable = previewAvailable;
  762. }
  763. public void setSharedViaLink(boolean sharedViaLink) {
  764. this.sharedViaLink = sharedViaLink;
  765. }
  766. public void setPermissions(String permissions) {
  767. this.permissions = permissions;
  768. }
  769. public void setRemoteId(String remoteId) {
  770. this.remoteId = remoteId;
  771. }
  772. public void setUpdateThumbnailNeeded(boolean updateThumbnailNeeded) {
  773. this.updateThumbnailNeeded = updateThumbnailNeeded;
  774. }
  775. public void setDownloading(boolean downloading) {
  776. this.downloading = downloading;
  777. }
  778. public void setEtagInConflict(String etagInConflict) {
  779. this.etagInConflict = etagInConflict;
  780. }
  781. public void setSharedWithSharee(boolean sharedWithSharee) {
  782. this.sharedWithSharee = sharedWithSharee;
  783. }
  784. public void setFavorite(boolean favorite) {
  785. this.favorite = favorite;
  786. }
  787. public void setHidden(boolean hidden) {
  788. this.hidden = hidden;
  789. }
  790. public void setEncrypted(boolean encrypted) {
  791. this.encrypted = encrypted;
  792. }
  793. public void setMountType(WebdavEntry.MountType mountType) {
  794. this.mountType = mountType;
  795. }
  796. public void setUnreadCommentsCount(int unreadCommentsCount) {
  797. this.unreadCommentsCount = unreadCommentsCount;
  798. }
  799. public void setOwnerId(String ownerId) {
  800. this.ownerId = ownerId;
  801. }
  802. public void setOwnerDisplayName(String ownerDisplayName) {
  803. this.ownerDisplayName = ownerDisplayName;
  804. }
  805. public void setNote(String note) {
  806. this.note = note;
  807. }
  808. public void setSharees(List<ShareeUser> sharees) {
  809. this.sharees = sharees;
  810. }
  811. public void setRichWorkspace(String richWorkspace) {
  812. this.richWorkspace = richWorkspace;
  813. }
  814. public long getFirstShareTimestamp() {
  815. return firstShareTimestamp;
  816. }
  817. public void setFirstShareTimestamp(long firstShareTimestamp) {
  818. this.firstShareTimestamp = firstShareTimestamp;
  819. }
  820. public boolean isLocked() {
  821. return locked;
  822. }
  823. public void setLocked(boolean locked) {
  824. this.locked = locked;
  825. }
  826. @Nullable
  827. public FileLockType getLockType() {
  828. return lockType;
  829. }
  830. public void setLockType(@Nullable FileLockType lockType) {
  831. this.lockType = lockType;
  832. }
  833. @Nullable
  834. public String getLockOwnerId() {
  835. return lockOwnerId;
  836. }
  837. public void setLockOwnerId(@Nullable String lockOwnerId) {
  838. this.lockOwnerId = lockOwnerId;
  839. }
  840. @Nullable
  841. public String getLockOwnerDisplayName() {
  842. return lockOwnerDisplayName;
  843. }
  844. public void setLockOwnerDisplayName(@Nullable String lockOwnerDisplayName) {
  845. this.lockOwnerDisplayName = lockOwnerDisplayName;
  846. }
  847. @Nullable
  848. public String getLockOwnerEditor() {
  849. return lockOwnerEditor;
  850. }
  851. public void setLockOwnerEditor(@Nullable String lockOwnerEditor) {
  852. this.lockOwnerEditor = lockOwnerEditor;
  853. }
  854. public long getLockTimestamp() {
  855. return lockTimestamp;
  856. }
  857. public void setLockTimestamp(long lockTimestamp) {
  858. this.lockTimestamp = lockTimestamp;
  859. }
  860. public long getLockTimeout() {
  861. return lockTimeout;
  862. }
  863. public void setLockTimeout(long lockTimeout) {
  864. this.lockTimeout = lockTimeout;
  865. }
  866. @Nullable
  867. public String getLockToken() {
  868. return lockToken;
  869. }
  870. public void setLockToken(@Nullable String lockToken) {
  871. this.lockToken = lockToken;
  872. }
  873. public void setImageDimension(@Nullable ImageDimension imageDimension) {
  874. this.imageDimension = imageDimension;
  875. }
  876. @Nullable
  877. public ImageDimension getImageDimension() {
  878. return imageDimension;
  879. }
  880. public void setGeoLocation(@Nullable GeoLocation geolocation) {
  881. this.geolocation = geolocation;
  882. }
  883. @Nullable
  884. public GeoLocation getGeoLocation() {
  885. return geolocation;
  886. }
  887. public List<String> getTags() {
  888. return tags;
  889. }
  890. public void setTags(List<String> tags) {
  891. this.tags = tags;
  892. }
  893. public long getE2eCounter() {
  894. return e2eCounter;
  895. }
  896. public void setE2eCounter(@Nullable Long e2eCounter) {
  897. if (e2eCounter == null) {
  898. this.e2eCounter = -1;
  899. } else {
  900. this.e2eCounter = e2eCounter;
  901. }
  902. }
  903. }