Unshare public link in ShareFileFragment
[pub/Android/ownCloud.git] / src / com / owncloud / android / files / FileOperationsHelper.java
1 /**
2 * ownCloud Android client application
3 *
4 * @author masensio
5 * @author David A. Velasco
6 * Copyright (C) 2015 ownCloud Inc.
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2,
10 * as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22 package com.owncloud.android.files;
23
24 import android.accounts.Account;
25 import android.content.ActivityNotFoundException;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.pm.PackageManager;
29 import android.content.pm.ResolveInfo;
30 import android.net.Uri;
31 import android.support.v4.app.DialogFragment;
32 import android.webkit.MimeTypeMap;
33 import android.widget.Toast;
34
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.network.WebdavUtils;
41 import com.owncloud.android.lib.common.utils.Log_OC;
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
50 import org.apache.http.protocol.HTTP;
51
52 import java.util.List;
53
54 /**
55 *
56 */
57 public class FileOperationsHelper {
58
59 private static final String TAG = FileOperationsHelper.class.getName();
60
61 private static final String FTAG_CHOOSER_DIALOG = "CHOOSER_DIALOG";
62
63 protected FileActivity mFileActivity = null;
64
65 /// Identifier of operation in progress which result shouldn't be lost
66 private long mWaitingForOpId = Long.MAX_VALUE;
67
68 public FileOperationsHelper(FileActivity fileActivity) {
69 mFileActivity = fileActivity;
70 }
71
72
73 public void openFile(OCFile file) {
74 if (file != null) {
75 String storagePath = file.getStoragePath();
76 String encodedStoragePath = WebdavUtils.encodePath(storagePath);
77
78 Intent intentForSavedMimeType = new Intent(Intent.ACTION_VIEW);
79 intentForSavedMimeType.setDataAndType(Uri.parse("file://"+ encodedStoragePath),
80 file.getMimetype());
81 intentForSavedMimeType.setFlags(
82 Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
83 );
84
85 Intent intentForGuessedMimeType = null;
86 if (storagePath.lastIndexOf('.') >= 0) {
87 String guessedMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
88 storagePath.substring(storagePath.lastIndexOf('.') + 1)
89 );
90 if (guessedMimeType != null && !guessedMimeType.equals(file.getMimetype())) {
91 intentForGuessedMimeType = new Intent(Intent.ACTION_VIEW);
92 intentForGuessedMimeType.
93 setDataAndType(Uri.parse("file://"+ encodedStoragePath),
94 guessedMimeType);
95 intentForGuessedMimeType.setFlags(
96 Intent.FLAG_GRANT_READ_URI_PERMISSION |
97 Intent.FLAG_GRANT_WRITE_URI_PERMISSION
98 );
99 }
100 }
101
102 Intent openFileWithIntent;
103 if (intentForGuessedMimeType != null) {
104 openFileWithIntent = intentForGuessedMimeType;
105 } else {
106 openFileWithIntent = intentForSavedMimeType;
107 }
108
109 List<ResolveInfo> launchables = mFileActivity.getPackageManager().
110 queryIntentActivities(openFileWithIntent, PackageManager.GET_INTENT_FILTERS);
111
112 if(launchables != null && launchables.size() > 0) {
113 try {
114 mFileActivity.startActivity(
115 Intent.createChooser(
116 openFileWithIntent, mFileActivity.getString(R.string.actionbar_open_with)
117 )
118 );
119 } catch (ActivityNotFoundException anfe) {
120 showNoAppForFileTypeToast(mFileActivity.getApplicationContext());
121 }
122 } else {
123 showNoAppForFileTypeToast(mFileActivity.getApplicationContext());
124 }
125
126 } else {
127 Log_OC.wtf(TAG, "Trying to open a NULL OCFile");
128 }
129 }
130
131 /**
132 * Displays a toast stating that no application could be found to open the file.
133 *
134 * @param context the context to be able to show a toast.
135 */
136 private void showNoAppForFileTypeToast(Context context) {
137 Toast.makeText(context,
138 R.string.file_list_no_app_for_file_type, Toast.LENGTH_SHORT)
139 .show();
140 }
141
142
143 /**
144 * Helper method to share a file via a public link. Starts a request to do it in {@link OperationsService}
145 *
146 * @param file The file to share.
147 */
148 public void shareFileViaLink(OCFile file) {
149 if (isSharedSupported()) {
150 if (file != null) {
151 mFileActivity.showLoadingDialog(
152 mFileActivity.getApplicationContext().
153 getString(R.string.wait_a_moment)
154 );
155 Intent service = new Intent(mFileActivity, OperationsService.class);
156 service.setAction(OperationsService.ACTION_CREATE_SHARE_VIA_LINK);
157 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
158 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
159 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
160
161 } else {
162 Log_OC.wtf(TAG, "Trying to share a NULL OCFile");
163 // TODO user-level error?
164 }
165
166 } else {
167 // Show a Message
168 Toast t = Toast.makeText(
169 mFileActivity, mFileActivity.getString(R.string.share_link_no_support_share_api),
170 Toast.LENGTH_LONG
171 );
172 t.show();
173 }
174 }
175
176
177 public void shareFileWithLinkOLD(OCFile file) {
178
179 if (isSharedSupported()) {
180 if (file != null) {
181 String link = "https://fake.url";
182 Intent intent = createShareWithLinkIntent(link);
183 String[] packagesToExclude = new String[]{mFileActivity.getPackageName()};
184 DialogFragment chooserDialog = ShareLinkToDialog.newInstance(intent,
185 packagesToExclude, file);
186 chooserDialog.show(mFileActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG);
187
188 } else {
189 Log_OC.wtf(TAG, "Trying to share a NULL OCFile");
190 }
191
192 } else {
193 // Show a Message
194 Toast t = Toast.makeText(
195 mFileActivity, mFileActivity.getString(R.string.share_link_no_support_share_api),
196 Toast.LENGTH_LONG
197 );
198 t.show();
199 }
200 }
201
202
203 public void shareFileWithLinkToApp(OCFile file, String password, Intent sendIntent) {
204
205 if (file != null) {
206 mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
207 getString(R.string.wait_a_moment));
208
209 Intent service = new Intent(mFileActivity, OperationsService.class);
210 service.setAction(OperationsService.ACTION_CREATE_SHARE_VIA_LINK);
211 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
212 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
213 service.putExtra(OperationsService.EXTRA_PASSWORD_SHARE, password);
214 service.putExtra(OperationsService.EXTRA_SEND_INTENT, sendIntent);
215 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
216
217 } else {
218 Log_OC.wtf(TAG, "Trying to open a NULL OCFile");
219 }
220 }
221
222
223 private Intent createShareWithLinkIntent(String link) {
224 Intent intentToShareLink = new Intent(Intent.ACTION_SEND);
225 intentToShareLink.putExtra(Intent.EXTRA_TEXT, link);
226 intentToShareLink.setType(HTTP.PLAIN_TEXT_TYPE);
227 return intentToShareLink;
228 }
229
230
231 /**
232 * Helper method to share a file with a known sharee. Starts a request to do it in {@link OperationsService}
233 *
234 * @param file The file to share.
235 * @param shareeName Name (user name or group name) of the target sharee.
236 * @param shareType The share type determines the sharee type.
237 */
238 public void shareFileWithSharee(OCFile file, String shareeName, ShareType shareType) {
239 if (file != null) {
240 // TODO check capability?
241 mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
242 getString(R.string.wait_a_moment));
243
244 Intent service = new Intent(mFileActivity, OperationsService.class);
245 service.setAction(OperationsService.ACTION_CREATE_SHARE_WITH_SHAREE);
246 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
247 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
248 service.putExtra(OperationsService.EXTRA_SHARE_WITH, shareeName);
249 service.putExtra(OperationsService.EXTRA_SHARE_TYPE, shareType);
250 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
251
252 } else {
253 Log_OC.wtf(TAG, "Trying to share a NULL OCFile");
254 }
255 }
256
257
258 /**
259 * @return 'True' if the server supports the Share API
260 */
261 public boolean isSharedSupported() {
262 if (mFileActivity.getAccount() != null) {
263 OwnCloudVersion serverVersion = AccountUtils.getServerVersion(mFileActivity.getAccount());
264 return (serverVersion != null && serverVersion.isSharedSupported());
265 }
266 return false;
267 }
268
269
270 /**
271 * Helper method to unshare a file publicly shared via link.
272 * Starts a request to do it in {@link OperationsService}
273 *
274 * @param file The file to unshare.
275 */
276 public void unshareFileViaLink(OCFile file) {
277
278 // Unshare the file: Create the intent
279 Intent unshareService = new Intent(mFileActivity, OperationsService.class);
280 unshareService.setAction(OperationsService.ACTION_UNSHARE);
281 unshareService.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
282 unshareService.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
283 unshareService.putExtra(OperationsService.EXTRA_SHARE_TYPE, ShareType.PUBLIC_LINK);
284 unshareService.putExtra(OperationsService.EXTRA_SHARE_WITH, "");
285
286 unshareFile(unshareService);
287 }
288
289 public void unshareFileWithUserOrGroup(OCFile file, ShareType shareType, String userOrGroup){
290
291 // Unshare the file: Create the intent
292 Intent unshareService = new Intent(mFileActivity, OperationsService.class);
293 unshareService.setAction(OperationsService.ACTION_UNSHARE);
294 unshareService.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
295 unshareService.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
296 unshareService.putExtra(OperationsService.EXTRA_SHARE_TYPE, shareType);
297 unshareService.putExtra(OperationsService.EXTRA_SHARE_WITH, userOrGroup);
298
299 unshareFile(unshareService);
300 }
301
302
303 private void unshareFile(Intent unshareService){
304 if (isSharedSupported()) {
305 // Unshare the file
306 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().
307 queueNewOperation(unshareService);
308
309 mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
310 getString(R.string.wait_a_moment));
311
312 } else {
313 // Show a Message
314 Toast t = Toast.makeText(mFileActivity,
315 mFileActivity.getString(R.string.share_link_no_support_share_api),
316 Toast.LENGTH_LONG);
317 t.show();
318
319 }
320 }
321
322 /**
323 * Show an instance of {@link ShareType} for sharing or unsharing the {@OCFile} received as parameter.
324 *
325 * @param file File to share or unshare.
326 */
327 public void showShareFile(OCFile file){
328 Intent intent = new Intent(mFileActivity, ShareActivity.class);
329 intent.putExtra(mFileActivity.EXTRA_FILE, file);
330 intent.putExtra(mFileActivity.EXTRA_ACCOUNT, mFileActivity.getAccount());
331 mFileActivity.startActivity(intent);
332
333 }
334
335
336 /**
337 * @return 'True' if the server supports the Search Users API
338 */
339 public boolean isSearchUsersSupportedSupported() {
340 if (mFileActivity.getAccount() != null) {
341 OwnCloudVersion serverVersion = AccountUtils.getServerVersion(mFileActivity.getAccount());
342 return (serverVersion != null && serverVersion.isSearchUsersSupported());
343 }
344 return false;
345 }
346
347 public void sendDownloadedFile(OCFile file) {
348 if (file != null) {
349 String storagePath = file.getStoragePath();
350 String encodedStoragePath = WebdavUtils.encodePath(storagePath);
351 Intent sendIntent = new Intent(android.content.Intent.ACTION_SEND);
352 // set MimeType
353 sendIntent.setType(file.getMimetype());
354 sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + encodedStoragePath));
355 sendIntent.putExtra(Intent.ACTION_SEND, true); // Send Action
356
357 // Show dialog, without the own app
358 String[] packagesToExclude = new String[]{mFileActivity.getPackageName()};
359 DialogFragment chooserDialog = ShareLinkToDialog.newInstance(sendIntent,
360 packagesToExclude, file);
361 chooserDialog.show(mFileActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG);
362
363 } else {
364 Log_OC.wtf(TAG, "Trying to send a NULL OCFile");
365 }
366 }
367
368 /**
369 * Request the synchronization of a file or folder with the OC server, including its contents.
370 *
371 * @param file The file or folder to synchronize
372 */
373 public void syncFile(OCFile file) {
374 if (!file.isFolder()){
375 Intent intent = new Intent(mFileActivity, OperationsService.class);
376 intent.setAction(OperationsService.ACTION_SYNC_FILE);
377 intent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
378 intent.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
379 intent.putExtra(OperationsService.EXTRA_SYNC_FILE_CONTENTS, true);
380 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(intent);
381 mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
382 getString(R.string.wait_a_moment));
383
384 } else {
385 Intent intent = new Intent(mFileActivity, OperationsService.class);
386 intent.setAction(OperationsService.ACTION_SYNC_FOLDER);
387 intent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
388 intent.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
389 mFileActivity.startService(intent);
390
391 }
392 }
393
394 public void toggleFavorite(OCFile file, boolean isFavorite) {
395 file.setFavorite(isFavorite);
396 mFileActivity.getStorageManager().saveFile(file);
397
398 /// register the OCFile instance in the observer service to monitor local updates
399 Intent observedFileIntent = FileObserverService.makeObservedFileIntent(
400 mFileActivity,
401 file,
402 mFileActivity.getAccount(),
403 isFavorite);
404 mFileActivity.startService(observedFileIntent);
405
406 /// immediate content synchronization
407 if (file.isFavorite()) {
408 syncFile(file);
409 }
410 }
411
412 public void renameFile(OCFile file, String newFilename) {
413 // RenameFile
414 Intent service = new Intent(mFileActivity, OperationsService.class);
415 service.setAction(OperationsService.ACTION_RENAME);
416 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
417 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
418 service.putExtra(OperationsService.EXTRA_NEWNAME, newFilename);
419 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
420
421 mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
422 getString(R.string.wait_a_moment));
423 }
424
425
426 public void removeFile(OCFile file, boolean onlyLocalCopy) {
427 // RemoveFile
428 Intent service = new Intent(mFileActivity, OperationsService.class);
429 service.setAction(OperationsService.ACTION_REMOVE);
430 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
431 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
432 service.putExtra(OperationsService.EXTRA_REMOVE_ONLY_LOCAL, onlyLocalCopy);
433 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
434
435 mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
436 getString(R.string.wait_a_moment));
437 }
438
439
440 public void createFolder(String remotePath, boolean createFullPath) {
441 // Create Folder
442 Intent service = new Intent(mFileActivity, OperationsService.class);
443 service.setAction(OperationsService.ACTION_CREATE_FOLDER);
444 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
445 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, remotePath);
446 service.putExtra(OperationsService.EXTRA_CREATE_FULL_PATH, createFullPath);
447 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
448
449 mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
450 getString(R.string.wait_a_moment));
451 }
452
453 /**
454 * Cancel the transference in downloads (files/folders) and file uploads
455 * @param file OCFile
456 */
457 public void cancelTransference(OCFile file) {
458 Account account = mFileActivity.getAccount();
459 if (file.isFolder()) {
460 OperationsService.OperationsServiceBinder opsBinder =
461 mFileActivity.getOperationsServiceBinder();
462 if (opsBinder != null) {
463 opsBinder.cancel(account, file);
464 }
465 }
466
467 // for both files and folders
468 FileDownloaderBinder downloaderBinder = mFileActivity.getFileDownloaderBinder();
469 if (downloaderBinder != null && downloaderBinder.isDownloading(account, file)) {
470 downloaderBinder.cancel(account, file);
471 }
472 FileUploaderBinder uploaderBinder = mFileActivity.getFileUploaderBinder();
473 if (uploaderBinder != null && uploaderBinder.isUploading(account, file)) {
474 uploaderBinder.cancel(account, file);
475 }
476 }
477
478 /**
479 * Start move file operation
480 *
481 * @param newfile File where it is going to be moved
482 * @param currentFile File with the previous info
483 */
484 public void moveFile(OCFile newfile, OCFile currentFile) {
485 // Move files
486 Intent service = new Intent(mFileActivity, OperationsService.class);
487 service.setAction(OperationsService.ACTION_MOVE_FILE);
488 service.putExtra(OperationsService.EXTRA_NEW_PARENT_PATH, newfile.getRemotePath());
489 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, currentFile.getRemotePath());
490 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
491 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
492
493 mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
494 getString(R.string.wait_a_moment));
495 }
496
497 /**
498 * Start copy file operation
499 *
500 * @param newfile File where it is going to be moved
501 * @param currentFile File with the previous info
502 */
503 public void copyFile(OCFile newfile, OCFile currentFile) {
504 // Copy files
505 Intent service = new Intent(mFileActivity, OperationsService.class);
506 service.setAction(OperationsService.ACTION_COPY_FILE);
507 service.putExtra(OperationsService.EXTRA_NEW_PARENT_PATH, newfile.getRemotePath());
508 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, currentFile.getRemotePath());
509 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
510 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
511
512 mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
513 getString(R.string.wait_a_moment));
514 }
515
516 public long getOpIdWaitingFor() {
517 return mWaitingForOpId;
518 }
519
520
521 public void setOpIdWaitingFor(long waitingForOpId) {
522 mWaitingForOpId = waitingForOpId;
523 }
524
525 /**
526 * @return 'True' if the server doesn't need to check forbidden characters
527 */
528 public boolean isVersionWithForbiddenCharacters() {
529 if (mFileActivity.getAccount() != null) {
530 OwnCloudVersion serverVersion =
531 AccountUtils.getServerVersion(mFileActivity.getAccount());
532 return (serverVersion != null && serverVersion.isVersionWithForbiddenCharacters());
533 }
534 return false;
535 }
536
537 }