-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Expand file tree
/
Copy pathCloudUtil.java
More file actions
315 lines (286 loc) · 11.5 KB
/
CloudUtil.java
File metadata and controls
315 lines (286 loc) · 11.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
/*
* Copyright (C) 2014-2024 Arpit Khurana <arpitkh96@gmail.com>, Vishal Nehra <vishalmeham2@gmail.com>,
* Emmanuel Messulam<emmanuelbendavid@gmail.com>, Raymond Lai <airwave209gt at gmail.com> and Contributors.
*
* This file is part of Amaze File Manager.
*
* Amaze File Manager is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.amaze.filemanager.filesystem.cloud;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.amaze.filemanager.R;
import com.amaze.filemanager.adapters.data.IconDataParcelable;
import com.amaze.filemanager.database.CloudHandler;
import com.amaze.filemanager.fileoperations.exceptions.CloudPluginException;
import com.amaze.filemanager.fileoperations.filesystem.OpenMode;
import com.amaze.filemanager.fileoperations.filesystem.cloud.CloudStreamer;
import com.amaze.filemanager.filesystem.HybridFile;
import com.amaze.filemanager.filesystem.HybridFileParcelable;
import com.amaze.filemanager.ui.activities.MainActivity;
import com.amaze.filemanager.ui.icons.MimeTypes;
import com.amaze.filemanager.utils.DataUtils;
import com.amaze.filemanager.utils.OTGUtil;
import com.amaze.filemanager.utils.OnFileFound;
import com.cloudrail.si.interfaces.CloudStorage;
import com.cloudrail.si.types.CloudMetaData;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.documentfile.provider.DocumentFile;
import kotlin.Deprecated;
import kotlin.ReplaceWith;
/**
* Created by vishal on 19/4/17.
*
* <p>Class provides helper methods for cloud utilities
*/
public class CloudUtil {
private static final Logger LOG = LoggerFactory.getLogger(CloudUtil.class);
/**
* @deprecated use getCloudFiles()
*/
@Deprecated(replaceWith = @ReplaceWith(expression = "getCloudFiles", imports = ""), message = "")
public static ArrayList<HybridFileParcelable> listFiles(
String path, CloudStorage cloudStorage, OpenMode openMode) throws CloudPluginException {
final ArrayList<HybridFileParcelable> baseFiles = new ArrayList<>();
getCloudFiles(path, cloudStorage, openMode, baseFiles::add);
return baseFiles;
}
public static void getCloudFiles(
String path, CloudStorage cloudStorage, OpenMode openMode, OnFileFound fileFoundCallback)
throws CloudPluginException {
String strippedPath = stripPath(openMode, path);
try {
for (CloudMetaData cloudMetaData : cloudStorage.getChildren(strippedPath)) {
HybridFileParcelable baseFile =
new HybridFileParcelable(
path + "/" + cloudMetaData.getName(),
"",
(cloudMetaData.getModifiedAt() == null) ? 0l : cloudMetaData.getModifiedAt(),
cloudMetaData.getSize(),
cloudMetaData.getFolder());
baseFile.setName(cloudMetaData.getName());
baseFile.setMode(openMode);
fileFoundCallback.onFileFound(baseFile);
}
} catch (Exception e) {
LOG.warn("failed to get cloud files", e);
throw new CloudPluginException();
}
}
/** Strips down the cloud path to remove any prefix */
public static String stripPath(OpenMode openMode, String path) {
final String prefix;
switch (openMode) {
case DROPBOX:
prefix = CloudHandler.CLOUD_PREFIX_DROPBOX;
break;
case BOX:
prefix = CloudHandler.CLOUD_PREFIX_BOX;
break;
case ONEDRIVE:
prefix = CloudHandler.CLOUD_PREFIX_ONE_DRIVE;
break;
case GDRIVE:
prefix = CloudHandler.CLOUD_PREFIX_GOOGLE_DRIVE;
break;
default:
return path;
}
if (path.equals(prefix + "/")) {
// we're at root, just replace the prefix
return path.replace(prefix, "");
} else {
// we're not at root, replace prefix + /
// handle when paths are in format gdrive:/Documents // TODO: normalize drive paths
String pathReplaced = path.replace(prefix + "/", "");
if (pathReplaced.equals(path)) {
// we convert gdrive:/Documents to /Documents
return path.replace(prefix.substring(0, prefix.length() - 1), "");
}
return pathReplaced;
}
}
public static void launchCloud(
final HybridFile baseFile, final OpenMode serviceType, final Activity activity) {
final CloudStreamer streamer = CloudStreamer.getInstance();
new Thread(
() -> {
try {
streamer.setStreamSrc(
baseFile.getInputStream(activity),
baseFile.getName(activity),
baseFile.length(activity));
activity.runOnUiThread(
() -> {
try {
File file =
new File(
Uri.parse(CloudUtil.stripPath(serviceType, baseFile.getPath()))
.getPath());
Uri uri =
Uri.parse(CloudStreamer.URL + Uri.fromFile(file).getEncodedPath());
Intent i = new Intent(Intent.ACTION_VIEW);
i.setDataAndType(
uri,
MimeTypes.getMimeType(
baseFile.getPath(), baseFile.isDirectory(activity)));
PackageManager packageManager = activity.getPackageManager();
List<ResolveInfo> resInfos = packageManager.queryIntentActivities(i, 0);
if (resInfos != null && resInfos.size() > 0) activity.startActivity(i);
else
Toast.makeText(
activity,
activity.getString(R.string.smb_launch_error),
Toast.LENGTH_SHORT)
.show();
} catch (ActivityNotFoundException e) {
LOG.warn("failed to launch cloud file in activity", e);
}
});
} catch (Exception e) {
LOG.warn("failed to launch cloud file", e);
}
})
.start();
}
/**
* Asynctask checks if the item pressed on is a cloud account, and if the token that is saved for
* it is invalid or not, in which case, we'll clear off the saved token and authenticate the user
* again
*
* @param path the path of item in drawer
* @param mainActivity reference to main activity to fire callbacks to delete/add connection
*/
public static void checkToken(String path, final MainActivity mainActivity) {
new AsyncTask<String, Void, Boolean>() {
OpenMode serviceType;
@Override
protected Boolean doInBackground(String... params) {
final DataUtils dataUtils = DataUtils.getInstance();
boolean isTokenValid = true;
String path = params[0];
final CloudStorage cloudStorage;
if (path.startsWith(CloudHandler.CLOUD_PREFIX_DROPBOX)) {
// dropbox account
serviceType = OpenMode.DROPBOX;
cloudStorage = dataUtils.getAccount(OpenMode.DROPBOX);
} else if (path.startsWith(CloudHandler.CLOUD_PREFIX_ONE_DRIVE)) {
serviceType = OpenMode.ONEDRIVE;
cloudStorage = dataUtils.getAccount(OpenMode.ONEDRIVE);
} else if (path.startsWith(CloudHandler.CLOUD_PREFIX_BOX)) {
serviceType = OpenMode.BOX;
cloudStorage = dataUtils.getAccount(OpenMode.BOX);
} else if (path.startsWith(CloudHandler.CLOUD_PREFIX_GOOGLE_DRIVE)) {
serviceType = OpenMode.GDRIVE;
cloudStorage = dataUtils.getAccount(OpenMode.GDRIVE);
} else {
throw new IllegalStateException();
}
try {
cloudStorage.getUserLogin();
} catch (RuntimeException e) {
LOG.warn("Failed to validate user token for cloud connection", e);
isTokenValid = false;
}
return isTokenValid;
}
@Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
if (!aBoolean) {
// delete account and create a new one
Toast.makeText(
mainActivity,
mainActivity.getResources().getString(R.string.cloud_token_lost),
Toast.LENGTH_LONG)
.show();
mainActivity.deleteConnection(serviceType);
mainActivity.addConnection(serviceType);
}
}
}.execute(path);
}
/** Get an input stream for thumbnail for a given {@link IconDataParcelable} */
@Nullable
public static InputStream getThumbnailInputStreamForCloud(Context context, String path) {
InputStream inputStream;
HybridFile hybridFile = new HybridFile(OpenMode.UNKNOWN, path);
hybridFile.generateMode(context);
DataUtils dataUtils = DataUtils.getInstance();
switch (hybridFile.getMode()) {
case SFTP:
inputStream = hybridFile.getInputStream(context);
break;
case FTP:
// Until we find a way to properly handle threading issues with thread unsafe FTPClient,
// we refrain from loading any files via FTP as file thumbnail. - TranceLove
inputStream = null;
break;
case SMB:
try {
inputStream = hybridFile.getSmbFile().getInputStream();
} catch (IOException e) {
inputStream = null;
LOG.warn("failed to get inputstream for smb file for thumbnail", e);
}
break;
case OTG:
ContentResolver contentResolver = context.getContentResolver();
DocumentFile documentSourceFile =
OTGUtil.getDocumentFile(hybridFile.getPath(), context, false);
try {
inputStream = contentResolver.openInputStream(documentSourceFile.getUri());
} catch (FileNotFoundException e) {
LOG.warn("failed to get inputstream for otg for thumbnail", e);
inputStream = null;
}
break;
case DROPBOX:
case BOX:
case GDRIVE:
case ONEDRIVE:
OpenMode mode = hybridFile.getMode();
CloudStorage cloudStorageDropbox = dataUtils.getAccount(mode);
String stripped = CloudUtil.stripPath(mode, hybridFile.getPath());
inputStream = cloudStorageDropbox.getThumbnail(stripped);
break;
default:
try {
inputStream = new FileInputStream(hybridFile.getPath());
} catch (FileNotFoundException e) {
inputStream = null;
LOG.warn("failed to get inputstream for cloud files for thumbnail", e);
}
break;
}
return inputStream;
}
}