package com.openfarmanager.android.filesystem.actions.network; import android.net.Uri; import com.dropbox.client2.exception.DropboxException; import com.jcraft.jsch.SftpException; import com.mediafire.sdk.MFApiException; import com.mediafire.sdk.MFException; import com.mediafire.sdk.MFSessionNotStartedException; import com.mediafire.sdk.api.FileApi; import com.mediafire.sdk.api.responses.FileGetLinksResponse; import com.mediafire.sdk.api.responses.data_models.Link; import com.microsoft.live.LiveOperationException; import com.openfarmanager.android.App; import com.openfarmanager.android.core.network.dropbox.DropboxAPI; import com.openfarmanager.android.core.network.ftp.FtpAPI; import com.openfarmanager.android.core.network.ftp.SftpAPI; import com.openfarmanager.android.core.network.googledrive.GoogleDriveApi; import com.openfarmanager.android.core.network.mediafire.MediaFireApi; import com.openfarmanager.android.core.network.skydrive.SkyDriveAPI; import com.openfarmanager.android.core.network.smb.SmbAPI; import com.openfarmanager.android.core.network.webdav.WebDavApi; import com.openfarmanager.android.core.network.yandexdisk.YandexDiskApi; import com.openfarmanager.android.filesystem.DropboxFile; import com.openfarmanager.android.filesystem.FileProxy; import com.openfarmanager.android.filesystem.actions.OnActionListener; import com.openfarmanager.android.fragments.BaseFileSystemPanel; import com.openfarmanager.android.model.TaskStatusEnum; import com.openfarmanager.android.model.exeptions.NetworkException; import com.openfarmanager.android.model.exeptions.SdcardPermissionException; import com.openfarmanager.android.utils.SystemUtils; import com.yandex.disk.client.ProgressListener; import com.yandex.disk.client.exceptions.WebdavException; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.json.JSONException; import java.io.*; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Random; import jcifs.smb.SmbFileInputStream; import static com.openfarmanager.android.model.TaskStatusEnum.*; import static com.openfarmanager.android.utils.StorageUtils.checkForPermissionAndGetBaseUri; import static com.openfarmanager.android.utils.StorageUtils.checkUseStorageApi; import static com.openfarmanager.android.utils.StorageUtils.getStorageOutputFileStream; /** * @author Vlad Namashko */ public class CopyFromNetworkTask extends NetworkActionTask { private final static byte[] BUFFER = new byte[512 * 1024]; protected String mDestination; protected List<FileProxy> mItems; public CopyFromNetworkTask(BaseFileSystemPanel panel, List<FileProxy> items, String destination) { super(panel, new ArrayList<File>()); mDestination = destination; mItems = items; mNoProgress = true; } @Override protected TaskStatusEnum doInBackground(Void... voids) { // TODO: hack mDoneSize = 1; try { mSdCardPath = SystemUtils.getExternalStorage(mDestination); if (checkUseStorageApi(mSdCardPath)) { mUseStorageApi = true; mBaseUri = checkForPermissionAndGetBaseUri(); } } catch (SdcardPermissionException e) { return ERROR_STORAGE_PERMISSION_REQUIRED; } return doCopy(); } protected TaskStatusEnum doCopy() { // avoid concurrent modification ArrayList<FileProxy> items = new ArrayList<FileProxy>(mItems); for (FileProxy file : items) { if (isCancelled()) { return CANCELED; } try { switch (mNetworkType) { case SkyDrive: copyFromSkyDrive(file, mDestination); break; case Dropbox: copyFromDropbox(file, mDestination); break; case GoogleDrive: copyFromGoogleDrive(file, mDestination); break; case FTP: copyFromFTP(file, mDestination); break; case SFTP: copyFromSFTP(file, mDestination); break; case SMB: copyFromSmb(file, mDestination); break; case YandexDisk: copyFromYandexDisk(file, mDestination); break; case MediaFire: copyFromMediafire(file, mDestination); break; case WebDav: copyFromWebDav(file, mDestination); break; } } catch (NullPointerException e) { return ERROR_FILE_NOT_EXISTS; } catch (InterruptedIOException e) { return CANCELED; } catch (IOException e) { return ERROR_COPY; } catch (IllegalArgumentException e) { return ERROR_COPY; } catch (DropboxException e) { return createNetworkError(NetworkException.handleNetworkException(e)); } catch (LiveOperationException e) { return ERROR_COPY; } catch (Exception e) { return ERROR_COPY; } } return TaskStatusEnum.OK; } @Override protected Object getExtra() { return mDestination; } private void copyFromGoogleDrive(FileProxy source, String destination) throws IOException { GoogleDriveApi api = App.sInstance.getGoogleDriveApi(); if (isCancelled()) { throw new InterruptedIOException(); } String fullSourceFilePath = destination + "/" + source.getName(); if (source.isDirectory()) { createDirectoryIfNotExists(destination); List<FileProxy> list = api.getDirectoryFiles(source.getFullPath()); if (list.size() == 0) { createDirectoryIfNotExists(fullSourceFilePath); } else { for (FileProxy file : list) { copyFromGoogleDrive(file, fullSourceFilePath); } } } else { createDirectoryIfNotExists(destination); File destinationFile = createFileIfNotExists(fullSourceFilePath); setCurrentFile(source); api.download(source, getOutputStream(mSdCardPath, mUseStorageApi, mBaseUri, destinationFile)); } } private void copyFromSkyDrive(FileProxy source, String destination) throws LiveOperationException, IOException, JSONException { SkyDriveAPI api = App.sInstance.getSkyDriveApi(); if (isCancelled()) { throw new InterruptedIOException(); } String fullSourceFilePath = destination + "/" + source.getName(); if (source.isDirectory()) { createDirectoryIfNotExists(destination); List<FileProxy> list = api.getDirectoryFiles(source.getFullPath()); if (list.size() == 0) { createDirectoryIfNotExists(fullSourceFilePath); } else { for (FileProxy file : list) { copyFromSkyDrive(file, fullSourceFilePath); } } } else { createDirectoryIfNotExists(destination); File destinationFile = createFileIfNotExists(fullSourceFilePath); setCurrentFile(source); api.download(source, getOutputStream(mSdCardPath, mUseStorageApi, mBaseUri, destinationFile)); } } private void copyFromDropbox(FileProxy source, String destination) throws DropboxException, IOException { DropboxAPI api = App.sInstance.getDropboxApi(); if (isCancelled()) { throw new InterruptedIOException(); } String fullSourceFilePath = destination + "/" + source.getName(); if (source.isDirectory()) { try { createDirectoryIfNotExists(destination); com.dropbox.client2.DropboxAPI.Entry currentNode = api.metadata(source.getFullPath(), -1, null, true, null); if (currentNode.contents.size() == 0) { createDirectoryIfNotExists(fullSourceFilePath); } else { for (com.dropbox.client2.DropboxAPI.Entry entry : currentNode.contents) { copyFromDropbox(new DropboxFile(entry), fullSourceFilePath); } } } catch (Exception e) { throw NetworkException.handleNetworkException(e); } } else { createDirectoryIfNotExists(destination); File destinationFile = createFileIfNotExists(fullSourceFilePath); setCurrentFile(source); api.getFile(source.getFullPath(), null, getOutputStream(mSdCardPath, mUseStorageApi, mBaseUri, destinationFile), null); } } private void copyFromFTP(FileProxy source, String destination) throws IOException { FtpAPI api = App.sInstance.getFtpApi(); if (isCancelled()) { throw new InterruptedIOException(); } String fullSourceFilePath = destination + "/" + source.getName(); if (source.isDirectory()) { try { createDirectoryIfNotExists(destination); List<FileProxy> files = api.getDirectoryFiles(source.getFullPath()); if (files.size() == 0) { createDirectoryIfNotExists(fullSourceFilePath); } else { for (FileProxy file : files) { copyFromFTP(file, fullSourceFilePath); } } } catch (Exception e) { throw NetworkException.handleNetworkException(e); } } else { createDirectoryIfNotExists(destination); File destinationFile = createFileIfNotExists(fullSourceFilePath); setCurrentFile(source); api.client().retrieveFile(source.getFullPath(), getOutputStream(mSdCardPath, mUseStorageApi, mBaseUri, destinationFile)); } } private void copyFromSFTP(FileProxy source, String destination) throws IOException, SftpException { SftpAPI api = App.sInstance.getSftpApi(); if (isCancelled()) { throw new InterruptedIOException(); } String fullSourceFilePath = destination + "/" + source.getName(); if (source.isDirectory()) { try { createDirectoryIfNotExists(destination); List<FileProxy> files = api.getDirectoryFiles(source.getFullPath()); if (files.size() == 0) { createDirectoryIfNotExists(fullSourceFilePath); } else { for (FileProxy file : files) { copyFromSFTP(file, fullSourceFilePath); } } } catch (Exception e) { throw NetworkException.handleNetworkException(e); } } else { createDirectoryIfNotExists(destination); File destinationFile = createFileIfNotExists(fullSourceFilePath); setCurrentFile(source); api.writeFileToStream(source.getFullPath(), getOutputStream(mSdCardPath, mUseStorageApi, mBaseUri, destinationFile)); } } private void copyFromSmb(FileProxy source, String destination) throws IOException { SmbAPI api = App.sInstance.getSmbAPI(); if (isCancelled()) { throw new InterruptedIOException(); } String fullSourceFilePath = destination + "/" + source.getName(); if (source.isDirectory()) { try { createDirectoryIfNotExists(destination); List<FileProxy> files = api.getDirectoryFiles(source.getFullPath()); if (files.size() == 0) { createDirectoryIfNotExists(fullSourceFilePath); } else { for (FileProxy file : files) { copyFromSmb(file, fullSourceFilePath); } } } catch (Exception e) { throw NetworkException.handleNetworkException(e); } } else { createDirectoryIfNotExists(destination); File destinationFile = createFileIfNotExists(fullSourceFilePath); setCurrentFile(source); SmbFileInputStream in = new SmbFileInputStream(api.createSmbFile(source.getFullPath())); OutputStream out = getOutputStream(mSdCardPath, mUseStorageApi, mBaseUri, destinationFile); int len; while ((len = in.read(BUFFER)) > 0) { out.write(BUFFER, 0, len); } out.close(); in.close(); } } private void copyFromYandexDisk(FileProxy source, String destination) throws IOException, WebdavException { YandexDiskApi api = App.sInstance.getYandexDiskApi(); if (isCancelled()) { throw new InterruptedIOException(); } String fullSourceFilePath = destination + "/" + source.getName(); if (source.isDirectory()) { try { createDirectoryIfNotExists(destination); List<FileProxy> files = api.getDirectoryFiles(source.getFullPath()); if (files.size() == 0) { createDirectoryIfNotExists(fullSourceFilePath); } else { for (FileProxy file : files) { copyFromYandexDisk(file, fullSourceFilePath); } } } catch (Exception e) { throw NetworkException.handleNetworkException(e); } } else { createDirectoryIfNotExists(destination); File destinationFile = createFileIfNotExists(fullSourceFilePath); setCurrentFile(source); api.client().downloadFile(source.getFullPath(), getOutputStream(mSdCardPath, mUseStorageApi, mBaseUri, destinationFile), new ProgressListener() { @Override public void updateProgress(long loaded, long total) { } @Override public boolean hasCancelled() { return false; } }); } } private void copyFromMediafire(FileProxy source, String destination) throws IOException, MFApiException, MFSessionNotStartedException, MFException { MediaFireApi api = App.sInstance.getMediaFireApi(); if (isCancelled()) { throw new InterruptedIOException(); } String fullSourceFilePath = destination + "/" + source.getName(); if (source.isDirectory()) { try { createDirectoryIfNotExists(destination); List<FileProxy> files = api.openDirectory(source.getFullPath()); if (files.size() == 0) { createDirectoryIfNotExists(fullSourceFilePath); } else { for (FileProxy file : files) { copyFromMediafire(file, fullSourceFilePath); } } } catch (Exception e) { throw NetworkException.handleNetworkException(e); } } else { createDirectoryIfNotExists(destination); File destinationFile = createFileIfNotExists(fullSourceFilePath); setCurrentFile(source); LinkedHashMap<String, Object> query = new LinkedHashMap<>(); query.put("quick_key", source.getId()); query.put("link_type", "direct_download"); FileGetLinksResponse response = FileApi.getLinks(api.getMediaFire(), query, "1.4", FileGetLinksResponse.class); Link link = response.getLinks()[new Random().nextInt(response.getLinks().length)]; HttpGet httpGet = new HttpGet(link.getDirectDownloadLink()); DefaultHttpClient httpClient = new DefaultHttpClient(); HttpResponse httpResponse = httpClient.execute(httpGet); StatusLine statusLine = httpResponse.getStatusLine(); if (statusLine.getStatusCode() > 200) throw new RuntimeException(); InputStream in = httpResponse.getEntity().getContent(); OutputStream out = getOutputStream(mSdCardPath, mUseStorageApi, mBaseUri, destinationFile); int len; while ((len = in.read(BUFFER)) > 0) { out.write(BUFFER, 0, len); } updateProgress(); out.close(); in.close(); } } private void copyFromWebDav(FileProxy source, String destination) throws Exception { WebDavApi api = App.sInstance.getWebDavApi(); if (isCancelled()) { throw new InterruptedIOException(); } String fullSourceFilePath = destination + "/" + source.getName(); if (source.isDirectory()) { try { createDirectoryIfNotExists(destination); List<FileProxy> files = api.getDirectoryFiles(source.getFullPath()); if (files.size() == 0) { createDirectoryIfNotExists(fullSourceFilePath); } else { for (FileProxy file : files) { copyFromWebDav(file, fullSourceFilePath); } } } catch (Exception e) { throw NetworkException.handleNetworkException(e); } } else { createDirectoryIfNotExists(destination); File destinationFile = createFileIfNotExists(fullSourceFilePath); setCurrentFile(source); InputStream in = api.getFromWebDav(source.getFullPath()); OutputStream out = getOutputStream(mSdCardPath, mUseStorageApi, mBaseUri, destinationFile); int len; while ((len = in.read(BUFFER)) > 0) { out.write(BUFFER, 0, len); } out.close(); in.close(); } } private File createFileIfNotExists(String fullSourceFilePath) throws IOException { File destinationFile = new File(fullSourceFilePath); if (!mUseStorageApi && !destinationFile.exists() && !destinationFile.createNewFile()) { throw new IOException(); } return destinationFile; } private void setCurrentFile(FileProxy source) { mCurrentFile = source.getName(); updateProgress(); } private static OutputStream getOutputStream(String sdCardPath, boolean useStorageApi, Uri baseUri, File outputFile) throws FileNotFoundException { return useStorageApi ? getStorageOutputFileStream(outputFile, baseUri, sdCardPath) : new FileOutputStream(outputFile); } }