FileOperationsHelper.java 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763
  1. /**
  2. * ownCloud Android client application
  3. *
  4. * @author masensio
  5. * @author David A. Velasco
  6. * @author Juan Carlos González Cabrero
  7. * Copyright (C) 2015 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.ui.helpers;
  23. import android.accounts.Account;
  24. import android.content.ActivityNotFoundException;
  25. import android.content.Context;
  26. import android.content.Intent;
  27. import android.content.pm.PackageManager;
  28. import android.content.pm.ResolveInfo;
  29. import android.net.Uri;
  30. import android.os.Parcelable;
  31. import android.support.annotation.Nullable;
  32. import android.support.v4.app.DialogFragment;
  33. import android.webkit.MimeTypeMap;
  34. import android.widget.Toast;
  35. import com.owncloud.android.R;
  36. import com.owncloud.android.authentication.AccountUtils;
  37. import com.owncloud.android.datamodel.OCFile;
  38. import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
  39. import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
  40. import com.owncloud.android.lib.common.utils.Log_OC;
  41. import com.owncloud.android.lib.resources.shares.OCShare;
  42. import com.owncloud.android.lib.resources.shares.ShareType;
  43. import com.owncloud.android.lib.resources.status.OwnCloudVersion;
  44. import com.owncloud.android.services.OperationsService;
  45. import com.owncloud.android.services.observer.FileObserverService;
  46. import com.owncloud.android.ui.activity.FileActivity;
  47. import com.owncloud.android.ui.activity.ShareActivity;
  48. import com.owncloud.android.ui.dialog.ShareLinkToDialog;
  49. import com.owncloud.android.ui.events.FavoriteEvent;
  50. import org.greenrobot.eventbus.EventBus;
  51. import java.io.BufferedReader;
  52. import java.io.FileInputStream;
  53. import java.io.IOException;
  54. import java.io.InputStreamReader;
  55. import java.util.ArrayList;
  56. import java.util.Collection;
  57. import java.util.List;
  58. import java.util.regex.Matcher;
  59. import java.util.regex.Pattern;
  60. /**
  61. *
  62. */
  63. public class FileOperationsHelper {
  64. private static final String TAG = FileOperationsHelper.class.getSimpleName();
  65. private static final String FTAG_CHOOSER_DIALOG = "CHOOSER_DIALOG";
  66. protected FileActivity mFileActivity = null;
  67. /// Identifier of operation in progress which result shouldn't be lost
  68. private long mWaitingForOpId = Long.MAX_VALUE;
  69. private static final Pattern mPatternUrl = Pattern.compile("^URL=(.+)$");
  70. private static final Pattern mPatternString = Pattern.compile("<string>(.+)</string>");
  71. public FileOperationsHelper(FileActivity fileActivity) {
  72. mFileActivity = fileActivity;
  73. }
  74. @Nullable
  75. private String getUrlFromFile(String storagePath, Pattern pattern) {
  76. String url = null;
  77. InputStreamReader fr = null;
  78. BufferedReader br = null;
  79. try {
  80. fr = new InputStreamReader(new FileInputStream(storagePath), "UTF8");
  81. br = new BufferedReader(fr);
  82. String line;
  83. while ((line = br.readLine()) != null) {
  84. Matcher m = pattern.matcher(line);
  85. if (m.find()) {
  86. url = m.group(1);
  87. break;
  88. }
  89. }
  90. } catch (IOException e) {
  91. Log_OC.d(TAG, e.getMessage());
  92. } finally {
  93. if (br != null) {
  94. try {
  95. br.close();
  96. } catch (IOException e) {
  97. Log_OC.d(TAG, "Error closing buffered reader for URL file", e);
  98. }
  99. }
  100. if (fr != null) {
  101. try {
  102. fr.close();
  103. } catch (IOException e) {
  104. Log_OC.d(TAG, "Error closing file reader for URL file", e);
  105. }
  106. }
  107. }
  108. return url;
  109. }
  110. @Nullable
  111. private Intent createIntentFromFile(String storagePath) {
  112. String url = null;
  113. int lastIndexOfDot = storagePath.lastIndexOf('.');
  114. if (lastIndexOfDot >= 0) {
  115. String fileExt = storagePath.substring(lastIndexOfDot + 1);
  116. if (fileExt.equalsIgnoreCase("url") ||fileExt.equalsIgnoreCase("desktop")) {
  117. // Windows internet shortcut file .url
  118. // Ubuntu internet shortcut file .desktop
  119. url = getUrlFromFile(storagePath, mPatternUrl);
  120. } else if (fileExt.equalsIgnoreCase("webloc")) {
  121. // mac internet shortcut file .webloc
  122. url = getUrlFromFile(storagePath, mPatternString);
  123. }
  124. }
  125. if (url == null) {
  126. return null;
  127. }
  128. return new Intent(Intent.ACTION_VIEW, Uri.parse(url));
  129. }
  130. public void openFile(OCFile file) {
  131. if (file != null) {
  132. String storagePath = file.getStoragePath();
  133. Intent openFileWithIntent = null;
  134. int lastIndexOfDot = storagePath.lastIndexOf('.');
  135. if (lastIndexOfDot >= 0) {
  136. String fileExt = storagePath.substring(lastIndexOfDot + 1);
  137. String guessedMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExt);
  138. if (guessedMimeType != null) {
  139. openFileWithIntent = new Intent(Intent.ACTION_VIEW);
  140. openFileWithIntent.setDataAndType(
  141. file.getExposedFileUri(mFileActivity),
  142. guessedMimeType
  143. );
  144. }
  145. }
  146. if(openFileWithIntent == null) {
  147. openFileWithIntent = createIntentFromFile(storagePath);
  148. }
  149. if (openFileWithIntent == null) {
  150. openFileWithIntent = new Intent(Intent.ACTION_VIEW);
  151. openFileWithIntent.setDataAndType(
  152. file.getExposedFileUri(mFileActivity),
  153. file.getMimetype()
  154. );
  155. }
  156. openFileWithIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
  157. List<ResolveInfo> launchables = mFileActivity.getPackageManager().
  158. queryIntentActivities(openFileWithIntent, PackageManager.GET_INTENT_FILTERS);
  159. if(launchables != null && launchables.size() > 0) {
  160. try {
  161. mFileActivity.startActivity(
  162. Intent.createChooser(
  163. openFileWithIntent, mFileActivity.getString(R.string.actionbar_open_with)
  164. )
  165. );
  166. } catch (ActivityNotFoundException anfe) {
  167. showNoAppForFileTypeToast(mFileActivity.getApplicationContext());
  168. }
  169. } else {
  170. showNoAppForFileTypeToast(mFileActivity.getApplicationContext());
  171. }
  172. } else {
  173. Log_OC.e(TAG, "Trying to open a NULL OCFile");
  174. }
  175. }
  176. /**
  177. * Displays a toast stating that no application could be found to open the file.
  178. *
  179. * @param context the context to be able to show a toast.
  180. */
  181. private void showNoAppForFileTypeToast(Context context) {
  182. Toast.makeText(context,
  183. R.string.file_list_no_app_for_file_type, Toast.LENGTH_SHORT)
  184. .show();
  185. }
  186. /**
  187. * Helper method to share a file via a public link. Starts a request to do it in {@link OperationsService}
  188. *
  189. * @param file The file to share.
  190. * @param password Optional password to protect the public share.
  191. */
  192. public void shareFileViaLink(OCFile file, String password) {
  193. if (isSharedSupported()) {
  194. if (file != null) {
  195. mFileActivity.showLoadingDialog(
  196. mFileActivity.getApplicationContext().
  197. getString(R.string.wait_a_moment)
  198. );
  199. Intent service = new Intent(mFileActivity, OperationsService.class);
  200. service.setAction(OperationsService.ACTION_CREATE_SHARE_VIA_LINK);
  201. service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  202. if (password != null && password.length() > 0) {
  203. service.putExtra(OperationsService.EXTRA_SHARE_PASSWORD, password);
  204. }
  205. service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
  206. mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
  207. } else {
  208. Log_OC.e(TAG, "Trying to share a NULL OCFile");
  209. // TODO user-level error?
  210. }
  211. } else {
  212. // Show a Message
  213. Toast t = Toast.makeText(
  214. mFileActivity, mFileActivity.getString(R.string.share_link_no_support_share_api),
  215. Toast.LENGTH_LONG
  216. );
  217. t.show();
  218. }
  219. }
  220. public void getFileWithLink(OCFile file){
  221. if (isSharedSupported()) {
  222. if (file != null) {
  223. mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
  224. getString(R.string.wait_a_moment));
  225. Intent service = new Intent(mFileActivity, OperationsService.class);
  226. service.setAction(OperationsService.ACTION_CREATE_SHARE_VIA_LINK);
  227. service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  228. service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
  229. mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
  230. } else {
  231. Log_OC.e(TAG, "Trying to share a NULL OCFile");
  232. }
  233. } else {
  234. // Show a Message
  235. Toast t = Toast.makeText(
  236. mFileActivity, mFileActivity.getString(R.string.share_link_no_support_share_api),
  237. Toast.LENGTH_LONG
  238. );
  239. t.show();
  240. }
  241. }
  242. /**
  243. * Helper method to share a file with a known sharee. Starts a request to do it in {@link OperationsService}
  244. *
  245. * @param file The file to share.
  246. * @param shareeName Name (user name or group name) of the target sharee.
  247. * @param shareType The share type determines the sharee type.
  248. * @param permissions Permissions to grant to sharee on the shared file.
  249. */
  250. public void shareFileWithSharee(OCFile file, String shareeName, ShareType shareType, int permissions) {
  251. if (file != null) {
  252. // TODO check capability?
  253. mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
  254. getString(R.string.wait_a_moment));
  255. Intent service = new Intent(mFileActivity, OperationsService.class);
  256. service.setAction(OperationsService.ACTION_CREATE_SHARE_WITH_SHAREE);
  257. service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  258. service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
  259. service.putExtra(OperationsService.EXTRA_SHARE_WITH, shareeName);
  260. service.putExtra(OperationsService.EXTRA_SHARE_TYPE, shareType);
  261. service.putExtra(OperationsService.EXTRA_SHARE_PERMISSIONS, permissions);
  262. mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
  263. } else {
  264. Log_OC.e(TAG, "Trying to share a NULL OCFile");
  265. }
  266. }
  267. /**
  268. * @return 'True' if the server supports the Share API
  269. */
  270. public boolean isSharedSupported() {
  271. if (mFileActivity.getAccount() != null) {
  272. OwnCloudVersion serverVersion = AccountUtils.getServerVersion(mFileActivity.getAccount());
  273. return (serverVersion != null && serverVersion.isSharedSupported());
  274. }
  275. return false;
  276. }
  277. /**
  278. * Helper method to unshare a file publicly shared via link.
  279. * Starts a request to do it in {@link OperationsService}
  280. *
  281. * @param file The file to unshare.
  282. */
  283. public void unshareFileViaLink(OCFile file) {
  284. // Unshare the file: Create the intent
  285. Intent unshareService = new Intent(mFileActivity, OperationsService.class);
  286. unshareService.setAction(OperationsService.ACTION_UNSHARE);
  287. unshareService.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  288. unshareService.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
  289. unshareService.putExtra(OperationsService.EXTRA_SHARE_TYPE, ShareType.PUBLIC_LINK);
  290. unshareService.putExtra(OperationsService.EXTRA_SHARE_WITH, "");
  291. queueShareIntent(unshareService);
  292. }
  293. public void unshareFileWithUserOrGroup(OCFile file, ShareType shareType, String userOrGroup){
  294. // Unshare the file: Create the intent
  295. Intent unshareService = new Intent(mFileActivity, OperationsService.class);
  296. unshareService.setAction(OperationsService.ACTION_UNSHARE);
  297. unshareService.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  298. unshareService.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
  299. unshareService.putExtra(OperationsService.EXTRA_SHARE_TYPE, shareType);
  300. unshareService.putExtra(OperationsService.EXTRA_SHARE_WITH, userOrGroup);
  301. queueShareIntent(unshareService);
  302. }
  303. private void queueShareIntent(Intent shareIntent){
  304. if (isSharedSupported()) {
  305. // Unshare the file
  306. mWaitingForOpId = mFileActivity.getOperationsServiceBinder().
  307. queueNewOperation(shareIntent);
  308. mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
  309. getString(R.string.wait_a_moment));
  310. } else {
  311. // Show a Message
  312. Toast t = Toast.makeText(mFileActivity,
  313. mFileActivity.getString(R.string.share_link_no_support_share_api),
  314. Toast.LENGTH_LONG);
  315. t.show();
  316. }
  317. }
  318. /**
  319. * Show an instance of {@link ShareType} for sharing or unsharing the {@OCFile} received as parameter.
  320. *
  321. * @param file File to share or unshare.
  322. */
  323. public void showShareFile(OCFile file){
  324. Intent intent = new Intent(mFileActivity, ShareActivity.class);
  325. intent.putExtra(mFileActivity.EXTRA_FILE, (Parcelable) file);
  326. intent.putExtra(mFileActivity.EXTRA_ACCOUNT, mFileActivity.getAccount());
  327. mFileActivity.startActivity(intent);
  328. }
  329. /**
  330. * Updates a public share on a file to set its password.
  331. * Starts a request to do it in {@link OperationsService}
  332. *
  333. * @param file File which public share will be protected with a password.
  334. * @param password Password to set for the public link; null or empty string to clear
  335. * the current password
  336. */
  337. public void setPasswordToShareViaLink(OCFile file, String password) {
  338. // Set password updating share
  339. Intent updateShareIntent = new Intent(mFileActivity, OperationsService.class);
  340. updateShareIntent.setAction(OperationsService.ACTION_UPDATE_SHARE);
  341. updateShareIntent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  342. updateShareIntent.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
  343. updateShareIntent.putExtra(
  344. OperationsService.EXTRA_SHARE_PASSWORD,
  345. (password == null) ? "" : password
  346. );
  347. queueShareIntent(updateShareIntent);
  348. }
  349. /**
  350. * Updates a public share on a file to set its expiration date.
  351. * Starts a request to do it in {@link OperationsService}
  352. *
  353. * @param file File which public share will be constrained with an expiration date.
  354. * @param expirationTimeInMillis Expiration date to set. A negative value clears the current expiration
  355. * date, leaving the link unrestricted. Zero makes no change.
  356. */
  357. public void setExpirationDateToShareViaLink(OCFile file, long expirationTimeInMillis) {
  358. Intent updateShareIntent = new Intent(mFileActivity, OperationsService.class);
  359. updateShareIntent.setAction(OperationsService.ACTION_UPDATE_SHARE);
  360. updateShareIntent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  361. updateShareIntent.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
  362. updateShareIntent.putExtra(
  363. OperationsService.EXTRA_SHARE_EXPIRATION_DATE_IN_MILLIS,
  364. expirationTimeInMillis
  365. );
  366. queueShareIntent(updateShareIntent);
  367. }
  368. /**
  369. * Updates a share on a file to set its access permissions.
  370. * Starts a request to do it in {@link OperationsService}
  371. *
  372. * @param share {@link OCShare} instance which permissions will be updated.
  373. * @param permissions New permissions to set. A value <= 0 makes no update.
  374. */
  375. public void setPermissionsToShare(OCShare share, int permissions) {
  376. Intent updateShareIntent = new Intent(mFileActivity, OperationsService.class);
  377. updateShareIntent.setAction(OperationsService.ACTION_UPDATE_SHARE);
  378. updateShareIntent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  379. updateShareIntent.putExtra(OperationsService.EXTRA_SHARE_ID, share.getId());
  380. updateShareIntent.putExtra(
  381. OperationsService.EXTRA_SHARE_PERMISSIONS,
  382. permissions
  383. );
  384. queueShareIntent(updateShareIntent);
  385. }
  386. /**
  387. * Updates a public share on a folder to set its editing permission.
  388. * Starts a request to do it in {@link OperationsService}
  389. *
  390. * @param folder Folder which editing permission of his public share will be modified.
  391. * @param uploadPermission New state of the permission for editing the folder shared via link.
  392. */
  393. public void setUploadPermissionsToShare(OCFile folder, boolean uploadPermission) {
  394. Intent updateShareIntent = new Intent(mFileActivity, OperationsService.class);
  395. updateShareIntent.setAction(OperationsService.ACTION_UPDATE_SHARE);
  396. updateShareIntent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  397. updateShareIntent.putExtra(OperationsService.EXTRA_REMOTE_PATH, folder.getRemotePath());
  398. updateShareIntent.putExtra(
  399. OperationsService.EXTRA_SHARE_PUBLIC_UPLOAD,
  400. uploadPermission
  401. );
  402. queueShareIntent(updateShareIntent);
  403. }
  404. /**
  405. * Updates a public share on a folder to set its hide file listing permission.
  406. * Starts a request to do it in {@link OperationsService}
  407. *
  408. * @param share {@link OCShare} instance which permissions will be updated.
  409. * @param hideFileListing New state of the permission for editing the folder shared via link.
  410. */
  411. public void setHideFileListingPermissionsToShare(OCShare share, boolean hideFileListing) {
  412. Intent updateShareIntent = new Intent(mFileActivity, OperationsService.class);
  413. updateShareIntent.setAction(OperationsService.ACTION_UPDATE_SHARE);
  414. updateShareIntent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  415. updateShareIntent.putExtra(OperationsService.EXTRA_SHARE_ID, share.getId());
  416. if (hideFileListing) {
  417. updateShareIntent.putExtra(OperationsService.EXTRA_SHARE_PERMISSIONS, OCShare.CREATE_PERMISSION_FLAG);
  418. } else {
  419. OwnCloudVersion serverVersion = AccountUtils.getServerVersion(mFileActivity.getAccount());
  420. if (serverVersion != null && serverVersion.isNotReshareableFederatedSupported()) {
  421. updateShareIntent.
  422. putExtra(OperationsService.EXTRA_SHARE_PERMISSIONS,
  423. OCShare.FEDERATED_PERMISSIONS_FOR_FOLDER_AFTER_OC9);
  424. } else {
  425. updateShareIntent.
  426. putExtra(OperationsService.EXTRA_SHARE_PERMISSIONS,
  427. OCShare.FEDERATED_PERMISSIONS_FOR_FOLDER_UP_TO_OC9);
  428. }
  429. }
  430. queueShareIntent(updateShareIntent);
  431. }
  432. /**
  433. * @return 'True' if the server supports the Search Users API
  434. */
  435. public boolean isSearchUserSupportedSupported() {
  436. if (mFileActivity.getAccount() != null) {
  437. OwnCloudVersion serverVersion = AccountUtils.getServerVersion(mFileActivity.getAccount());
  438. return (serverVersion != null && serverVersion.isSearchUsersSupported());
  439. }
  440. return false;
  441. }
  442. public void sendDownloadedFile(OCFile file) {
  443. if (file != null) {
  444. Intent sendIntent = new Intent(Intent.ACTION_SEND);
  445. // set MimeType
  446. sendIntent.setType(file.getMimetype());
  447. sendIntent.putExtra(
  448. Intent.EXTRA_STREAM,
  449. file.getExposedFileUri(mFileActivity)
  450. );
  451. sendIntent.putExtra(Intent.ACTION_SEND, true); // Send Action
  452. // Show dialog, without the own app
  453. String[] packagesToExclude = new String[]{mFileActivity.getPackageName()};
  454. DialogFragment chooserDialog = ShareLinkToDialog.newInstance(sendIntent, packagesToExclude);
  455. chooserDialog.show(mFileActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG);
  456. } else {
  457. Log_OC.e(TAG, "Trying to send a NULL OCFile");
  458. }
  459. }
  460. public void syncFiles(Collection<OCFile> files) {
  461. for (OCFile file: files) {
  462. syncFile(file);
  463. }
  464. }
  465. /**
  466. * Request the synchronization of a file or folder with the OC server, including its contents.
  467. *
  468. * @param file The file or folder to synchronize
  469. */
  470. public void syncFile(OCFile file) {
  471. if (!file.isFolder()){
  472. Intent intent = new Intent(mFileActivity, OperationsService.class);
  473. intent.setAction(OperationsService.ACTION_SYNC_FILE);
  474. intent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  475. intent.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
  476. intent.putExtra(OperationsService.EXTRA_SYNC_FILE_CONTENTS, true);
  477. mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(intent);
  478. mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
  479. getString(R.string.wait_a_moment));
  480. } else {
  481. Intent intent = new Intent(mFileActivity, OperationsService.class);
  482. intent.setAction(OperationsService.ACTION_SYNC_FOLDER);
  483. intent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  484. intent.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
  485. mFileActivity.startService(intent);
  486. }
  487. }
  488. public void toggleFavoriteFiles(Collection<OCFile> files, boolean shouldBeFavorite) {
  489. List<OCFile> alreadyRightStateList = new ArrayList<>();
  490. for(OCFile file : files) {
  491. if(file.getIsFavorite() == shouldBeFavorite) {
  492. alreadyRightStateList.add(file);
  493. }
  494. }
  495. files.removeAll(alreadyRightStateList);
  496. for (OCFile file: files) {
  497. toggleFavoriteFile(file, shouldBeFavorite);
  498. }
  499. }
  500. public void toggleFavoriteFile(OCFile file, boolean shouldBeFavorite) {
  501. if(file.getIsFavorite() != shouldBeFavorite) {
  502. EventBus.getDefault().post(new FavoriteEvent(file.getRemotePath(), shouldBeFavorite, file.getRemoteId()));
  503. }
  504. }
  505. public void toogleOfflineFiles(Collection<OCFile> files, boolean isAvailableOffline){
  506. List<OCFile> alreadyRightStateList = new ArrayList<>();
  507. for(OCFile file : files) {
  508. if(file.isAvailableOffline() == isAvailableOffline) {
  509. alreadyRightStateList.add(file);
  510. }
  511. }
  512. files.removeAll(alreadyRightStateList);
  513. for (OCFile file: files) {
  514. toggleOfflineFile(file, isAvailableOffline);
  515. }
  516. }
  517. public void toggleOfflineFile(OCFile file, boolean isAvailableOffline) {
  518. if (file.isAvailableOffline() != isAvailableOffline) {
  519. file.setAvailableOffline(isAvailableOffline);
  520. mFileActivity.getStorageManager().saveFile(file);
  521. /// register the OCFile instance in the observer service to monitor local updates
  522. Intent observedFileIntent = FileObserverService.makeObservedFileIntent(
  523. mFileActivity,
  524. file,
  525. mFileActivity.getAccount(),
  526. isAvailableOffline);
  527. mFileActivity.startService(observedFileIntent);
  528. /// immediate content synchronization
  529. if (file.isAvailableOffline()) {
  530. syncFile(file);
  531. }
  532. }
  533. }
  534. public void renameFile(OCFile file, String newFilename) {
  535. // RenameFile
  536. Intent service = new Intent(mFileActivity, OperationsService.class);
  537. service.setAction(OperationsService.ACTION_RENAME);
  538. service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  539. service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
  540. service.putExtra(OperationsService.EXTRA_NEWNAME, newFilename);
  541. mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
  542. mFileActivity.showLoadingDialog(mFileActivity.getString(R.string.wait_a_moment));
  543. }
  544. /**
  545. * Start operations to delete one or several files
  546. *
  547. * @param files Files to delete
  548. * @param onlyLocalCopy When 'true' only local copy of the files is removed; otherwise files are also deleted
  549. * in the server.
  550. */
  551. public void removeFiles(Collection<OCFile> files, boolean onlyLocalCopy) {
  552. for (OCFile file : files) {
  553. // RemoveFile
  554. Intent service = new Intent(mFileActivity, OperationsService.class);
  555. service.setAction(OperationsService.ACTION_REMOVE);
  556. service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  557. service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
  558. service.putExtra(OperationsService.EXTRA_REMOVE_ONLY_LOCAL, onlyLocalCopy);
  559. mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
  560. }
  561. mFileActivity.showLoadingDialog(mFileActivity.getString(R.string.wait_a_moment));
  562. }
  563. public void createFolder(String remotePath, boolean createFullPath) {
  564. // Create Folder
  565. Intent service = new Intent(mFileActivity, OperationsService.class);
  566. service.setAction(OperationsService.ACTION_CREATE_FOLDER);
  567. service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  568. service.putExtra(OperationsService.EXTRA_REMOTE_PATH, remotePath);
  569. service.putExtra(OperationsService.EXTRA_CREATE_FULL_PATH, createFullPath);
  570. mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
  571. mFileActivity.showLoadingDialog(mFileActivity.getString(R.string.wait_a_moment));
  572. }
  573. /**
  574. * Cancel the transference in downloads (files/folders) and file uploads
  575. * @param file OCFile
  576. */
  577. public void cancelTransference(OCFile file) {
  578. Account account = mFileActivity.getAccount();
  579. if (file.isFolder()) {
  580. OperationsService.OperationsServiceBinder opsBinder =
  581. mFileActivity.getOperationsServiceBinder();
  582. if (opsBinder != null) {
  583. opsBinder.cancel(account, file);
  584. }
  585. }
  586. // for both files and folders
  587. FileDownloaderBinder downloaderBinder = mFileActivity.getFileDownloaderBinder();
  588. if (downloaderBinder != null && downloaderBinder.isDownloading(account, file)) {
  589. downloaderBinder.cancel(account, file);
  590. }
  591. FileUploaderBinder uploaderBinder = mFileActivity.getFileUploaderBinder();
  592. if (uploaderBinder != null && uploaderBinder.isUploading(account, file)) {
  593. uploaderBinder.cancel(account, file);
  594. }
  595. }
  596. /**
  597. * Start operations to move one or several files
  598. *
  599. * @param files Files to move
  600. * @param targetFolder Folder where the files while be moved into
  601. */
  602. public void moveFiles(Collection<OCFile> files, OCFile targetFolder) {
  603. for (OCFile file : files) {
  604. Intent service = new Intent(mFileActivity, OperationsService.class);
  605. service.setAction(OperationsService.ACTION_MOVE_FILE);
  606. service.putExtra(OperationsService.EXTRA_NEW_PARENT_PATH, targetFolder.getRemotePath());
  607. service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
  608. service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  609. mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
  610. }
  611. mFileActivity.showLoadingDialog(mFileActivity.getString(R.string.wait_a_moment));
  612. }
  613. /**
  614. * Start operations to copy one or several files
  615. *
  616. * @param files Files to copy
  617. * @param targetFolder Folder where the files while be copied into
  618. */
  619. public void copyFiles(Collection<OCFile> files, OCFile targetFolder) {
  620. for (OCFile file : files) {
  621. Intent service = new Intent(mFileActivity, OperationsService.class);
  622. service.setAction(OperationsService.ACTION_COPY_FILE);
  623. service.putExtra(OperationsService.EXTRA_NEW_PARENT_PATH, targetFolder.getRemotePath());
  624. service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
  625. service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  626. mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
  627. }
  628. mFileActivity.showLoadingDialog(mFileActivity.getString(R.string.wait_a_moment));
  629. }
  630. public long getOpIdWaitingFor() {
  631. return mWaitingForOpId;
  632. }
  633. public void setOpIdWaitingFor(long waitingForOpId) {
  634. mWaitingForOpId = waitingForOpId;
  635. }
  636. /**
  637. * @return 'True' if the server doesn't need to check forbidden characters
  638. */
  639. public boolean isVersionWithForbiddenCharacters() {
  640. if (mFileActivity.getAccount() != null) {
  641. OwnCloudVersion serverVersion =
  642. AccountUtils.getServerVersion(mFileActivity.getAccount());
  643. return (serverVersion != null && serverVersion.isVersionWithForbiddenCharacters());
  644. }
  645. return false;
  646. }
  647. /**
  648. * Starts a check of the currenlty stored credentials for the given account.
  649. *
  650. * @param account OC account which credentials will be checked.
  651. */
  652. public void checkCurrentCredentials(Account account) {
  653. Intent service = new Intent(mFileActivity, OperationsService.class);
  654. service.setAction(OperationsService.ACTION_CHECK_CURRENT_CREDENTIALS);
  655. service.putExtra(OperationsService.EXTRA_ACCOUNT, account);
  656. mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
  657. mFileActivity.showLoadingDialog(
  658. mFileActivity.getString(R.string.wait_checking_credentials)
  659. );
  660. }
  661. }