OCFile.java 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042
  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 Integer getFileOverlayIcon(boolean isAutoUploadFolder) {
  590. if (WebdavEntry.MountType.GROUP == mountType || isGroupFolder()) {
  591. return R.drawable.ic_folder_overlay_account_group;
  592. } else if (sharedViaLink && !encrypted) {
  593. return R.drawable.ic_folder_overlay_link;
  594. } else if (isSharedWithMe() || sharedWithSharee) {
  595. return R.drawable.ic_folder_overlay_share;
  596. } else if (encrypted) {
  597. return R.drawable.ic_folder_overlay_key;
  598. } else if (WebdavEntry.MountType.EXTERNAL == mountType) {
  599. return R.drawable.ic_folder_overlay_external;
  600. } else if (locked) {
  601. return R.drawable.ic_folder_overlay_lock;
  602. } else if (isAutoUploadFolder) {
  603. return R.drawable.ic_folder_overlay_upload;
  604. } else {
  605. return null;
  606. }
  607. }
  608. public LayerDrawable getFileIcon(boolean isAutoUploadFolder, Context context) {
  609. Drawable folderDrawable = ContextCompat.getDrawable(context, R.drawable.folder);
  610. LayerDrawable folderLayerDrawable = new LayerDrawable(new Drawable[] { folderDrawable } );
  611. Integer overlayIconId = getFileOverlayIcon(isAutoUploadFolder);
  612. if (overlayIconId == null || folderDrawable == null) {
  613. return folderLayerDrawable;
  614. }
  615. Drawable overlayDrawable = ContextCompat.getDrawable(context, overlayIconId);
  616. if (overlayDrawable == null) {
  617. return folderLayerDrawable;
  618. }
  619. DrawableUtil drawableUtil = new DrawableUtil();
  620. return drawableUtil.addDrawableAsOverlay(folderDrawable, overlayDrawable, 6);
  621. }
  622. public static final Parcelable.Creator<OCFile> CREATOR = new Parcelable.Creator<OCFile>() {
  623. @Override
  624. public OCFile createFromParcel(Parcel source) {
  625. return new OCFile(source);
  626. }
  627. @Override
  628. public OCFile[] newArray(int size) {
  629. return new OCFile[size];
  630. }
  631. };
  632. /**
  633. * Android's internal ID of the file
  634. */
  635. public long getFileId() {
  636. return this.fileId;
  637. }
  638. public long getParentId() {
  639. return this.parentId;
  640. }
  641. public long getFileLength() {
  642. return this.fileLength;
  643. }
  644. public long getCreationTimestamp() {
  645. return this.creationTimestamp;
  646. }
  647. /**
  648. * @return unix timestamp in milliseconds
  649. */
  650. public long getModificationTimestamp() {
  651. return this.modificationTimestamp;
  652. }
  653. public long getUploadTimestamp() {
  654. return this.uploadTimestamp;
  655. }
  656. public long getModificationTimestampAtLastSyncForData() {
  657. return this.modificationTimestampAtLastSyncForData;
  658. }
  659. public String getMimeType() {
  660. return this.mimeType;
  661. }
  662. public boolean isNeedsUpdatingWhileSaving() {
  663. return this.needsUpdatingWhileSaving;
  664. }
  665. public long getLastSyncDateForProperties() {
  666. return this.lastSyncDateForProperties;
  667. }
  668. public long getLastSyncDateForData() {
  669. return this.lastSyncDateForData;
  670. }
  671. public boolean isPreviewAvailable() {
  672. return this.previewAvailable;
  673. }
  674. public String getEtag() {
  675. return this.etag;
  676. }
  677. public String getEtagOnServer() {
  678. return this.etagOnServer;
  679. }
  680. public boolean isSharedViaLink() {
  681. return this.sharedViaLink;
  682. }
  683. public String getPermissions() {
  684. return this.permissions;
  685. }
  686. public String getRemoteId() {
  687. return this.remoteId;
  688. }
  689. public boolean isUpdateThumbnailNeeded() {
  690. return this.updateThumbnailNeeded;
  691. }
  692. public boolean isDownloading() {
  693. return this.downloading;
  694. }
  695. public String getEtagInConflict() {
  696. return this.etagInConflict;
  697. }
  698. public boolean isSharedWithSharee() {
  699. return this.sharedWithSharee;
  700. }
  701. public boolean isFavorite() {
  702. return this.favorite;
  703. }
  704. public boolean isEncrypted() {
  705. return this.encrypted;
  706. }
  707. public WebdavEntry.MountType getMountType() {
  708. return this.mountType;
  709. }
  710. public int getUnreadCommentsCount() {
  711. return this.unreadCommentsCount;
  712. }
  713. public String getOwnerId() {
  714. return this.ownerId;
  715. }
  716. public String getOwnerDisplayName() {
  717. return this.ownerDisplayName;
  718. }
  719. public String getNote() {
  720. return this.note;
  721. }
  722. public List<ShareeUser> getSharees() {
  723. return this.sharees;
  724. }
  725. public String getRichWorkspace() {
  726. return this.richWorkspace;
  727. }
  728. public void setFileId(long fileId) {
  729. this.fileId = fileId;
  730. }
  731. public void setLocalId(long localId) {
  732. this.localId = localId;
  733. }
  734. public void setParentId(long parentId) {
  735. this.parentId = parentId;
  736. }
  737. public void setFileLength(long fileLength) {
  738. this.fileLength = fileLength;
  739. }
  740. public void setCreationTimestamp(long creationTimestamp) {
  741. this.creationTimestamp = creationTimestamp;
  742. }
  743. public void setModificationTimestamp(long modificationTimestamp) {
  744. this.modificationTimestamp = modificationTimestamp;
  745. }
  746. public void setModificationTimestampAtLastSyncForData(long modificationTimestampAtLastSyncForData) {
  747. this.modificationTimestampAtLastSyncForData = modificationTimestampAtLastSyncForData;
  748. }
  749. public void setRemotePath(String remotePath) {
  750. this.remotePath = remotePath;
  751. }
  752. public void setMimeType(String mimeType) {
  753. this.mimeType = mimeType;
  754. }
  755. public void setLastSyncDateForProperties(long lastSyncDateForProperties) {
  756. this.lastSyncDateForProperties = lastSyncDateForProperties;
  757. }
  758. public void setLastSyncDateForData(long lastSyncDateForData) {
  759. this.lastSyncDateForData = lastSyncDateForData;
  760. }
  761. public void setPreviewAvailable(boolean previewAvailable) {
  762. this.previewAvailable = previewAvailable;
  763. }
  764. public void setSharedViaLink(boolean sharedViaLink) {
  765. this.sharedViaLink = sharedViaLink;
  766. }
  767. public void setPermissions(String permissions) {
  768. this.permissions = permissions;
  769. }
  770. public void setRemoteId(String remoteId) {
  771. this.remoteId = remoteId;
  772. }
  773. public void setUpdateThumbnailNeeded(boolean updateThumbnailNeeded) {
  774. this.updateThumbnailNeeded = updateThumbnailNeeded;
  775. }
  776. public void setDownloading(boolean downloading) {
  777. this.downloading = downloading;
  778. }
  779. public void setEtagInConflict(String etagInConflict) {
  780. this.etagInConflict = etagInConflict;
  781. }
  782. public void setSharedWithSharee(boolean sharedWithSharee) {
  783. this.sharedWithSharee = sharedWithSharee;
  784. }
  785. public void setFavorite(boolean favorite) {
  786. this.favorite = favorite;
  787. }
  788. public void setEncrypted(boolean encrypted) {
  789. this.encrypted = encrypted;
  790. }
  791. public void setMountType(WebdavEntry.MountType mountType) {
  792. this.mountType = mountType;
  793. }
  794. public void setUnreadCommentsCount(int unreadCommentsCount) {
  795. this.unreadCommentsCount = unreadCommentsCount;
  796. }
  797. public void setOwnerId(String ownerId) {
  798. this.ownerId = ownerId;
  799. }
  800. public void setOwnerDisplayName(String ownerDisplayName) {
  801. this.ownerDisplayName = ownerDisplayName;
  802. }
  803. public void setNote(String note) {
  804. this.note = note;
  805. }
  806. public void setSharees(List<ShareeUser> sharees) {
  807. this.sharees = sharees;
  808. }
  809. public void setRichWorkspace(String richWorkspace) {
  810. this.richWorkspace = richWorkspace;
  811. }
  812. public long getFirstShareTimestamp() {
  813. return firstShareTimestamp;
  814. }
  815. public void setFirstShareTimestamp(long firstShareTimestamp) {
  816. this.firstShareTimestamp = firstShareTimestamp;
  817. }
  818. public boolean isLocked() {
  819. return locked;
  820. }
  821. public void setLocked(boolean locked) {
  822. this.locked = locked;
  823. }
  824. @Nullable
  825. public FileLockType getLockType() {
  826. return lockType;
  827. }
  828. public void setLockType(@Nullable FileLockType lockType) {
  829. this.lockType = lockType;
  830. }
  831. @Nullable
  832. public String getLockOwnerId() {
  833. return lockOwnerId;
  834. }
  835. public void setLockOwnerId(@Nullable String lockOwnerId) {
  836. this.lockOwnerId = lockOwnerId;
  837. }
  838. @Nullable
  839. public String getLockOwnerDisplayName() {
  840. return lockOwnerDisplayName;
  841. }
  842. public void setLockOwnerDisplayName(@Nullable String lockOwnerDisplayName) {
  843. this.lockOwnerDisplayName = lockOwnerDisplayName;
  844. }
  845. @Nullable
  846. public String getLockOwnerEditor() {
  847. return lockOwnerEditor;
  848. }
  849. public void setLockOwnerEditor(@Nullable String lockOwnerEditor) {
  850. this.lockOwnerEditor = lockOwnerEditor;
  851. }
  852. public long getLockTimestamp() {
  853. return lockTimestamp;
  854. }
  855. public void setLockTimestamp(long lockTimestamp) {
  856. this.lockTimestamp = lockTimestamp;
  857. }
  858. public long getLockTimeout() {
  859. return lockTimeout;
  860. }
  861. public void setLockTimeout(long lockTimeout) {
  862. this.lockTimeout = lockTimeout;
  863. }
  864. @Nullable
  865. public String getLockToken() {
  866. return lockToken;
  867. }
  868. public void setLockToken(@Nullable String lockToken) {
  869. this.lockToken = lockToken;
  870. }
  871. public void setImageDimension(@Nullable ImageDimension imageDimension) {
  872. this.imageDimension = imageDimension;
  873. }
  874. @Nullable
  875. public ImageDimension getImageDimension() {
  876. return imageDimension;
  877. }
  878. public void setGeoLocation(@Nullable GeoLocation geolocation) {
  879. this.geolocation = geolocation;
  880. }
  881. @Nullable
  882. public GeoLocation getGeoLocation() {
  883. return geolocation;
  884. }
  885. public List<String> getTags() {
  886. return tags;
  887. }
  888. public void setTags(List<String> tags) {
  889. this.tags = tags;
  890. }
  891. }