OCFile.java 30 KB

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