OCFile.java 30 KB

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